ZSTD vs Brotli vs GZIP: scegliere la compressione per le API
Confronta ZSTD, Brotli e GZIP per le API: velocità, rapporto di compressione, costo CPU e impostazioni pratiche per payload JSON e binari in produzione.

Cos'è la compressione API (e quando conviene)
La compressione delle risposte API significa che il server codifica il corpo della risposta (spesso JSON) in un flusso di byte più piccolo prima di inviarlo sulla rete. Il client (browser, app mobile, SDK o altro servizio) poi lo decomprime. Su HTTP, questo viene negoziato tramite intestazioni come Accept-Encoding (cosa supporta il client) e Content-Encoding (cosa ha scelto il server).
Cosa porta alle API
La compressione ti dà principalmente tre vantaggi:
- Meno banda: le risposte più piccole consumano meno byte end‑to‑end.
- Meno latenza su link limitati: meno byte spesso significa download più veloci su mobile, Wi‑Fi congestionato e chiamate cross‑region.
- Meno costi di egress: se paghi per i dati in uscita, ridurre la dimensione trasferita può abbassare direttamente la bolletta.
Lo scambio è semplice: la compressione risparmia banda ma costa CPU (compress/decompress) e talvolta memoria (buffer). Se vale la pena dipende dal collo di bottiglia del tuo sistema.
Quando la compressione aiuta di più
La compressione brilla quando le risposte sono:
- Ricche di testo e ripetitive, come JSON, risposte GraphQL, HTML o log.
- Medie o grandi, dove risparmiare decine o centinaia di kilobyte conta.
- Servite su reti lente o costose, ad esempio client mobile, traffico internazionale o chiamate cross‑region.
Se ritorni grandi liste JSON (cataloghi, risultati di ricerca, analytics), la compressione è spesso una delle vittorie più semplici.
Quando aiuta meno
La compressione è spesso uno spreco di CPU quando le risposte sono:
- Piccole (per esempio poche centinaia di byte). L'overhead di header + CPU può superare il risparmio.
- Già compresse (JPEG/PNG, MP4, ZIP, molti PDF). Ricomprimere di solito dà pochi benefici e a volte aumenta la dimensione.
- Servizi CPU‑bound (endpoint affollati che già lottano con il calcolo). Aggiungere compressione può aumentare la latenza di tail.
Gli assi decisionali che userai in questa guida
Quando scegli tra ZSTD vs Brotli vs GZIP per la compressione API, la decisione pratica spesso si riduce a:
- Riduzione della dimensione (rapporto di compressione)
- Latenza (tempo server fino al primo byte più tempo di decodifica client)
- Supporto client (cosa i tuoi chiamanti e gli intermediari gestiscono in modo affidabile)
Tutto il resto di questo articolo riguarda bilanciare questi tre fattori per la tua API e i tuoi pattern di traffico.
ZSTD vs Brotli vs GZIP: confronto rapido
Tutti e tre riducono la dimensione del payload, ma ottimizzano per vincoli diversi—velocità, rapporto di compressione e compatibilità.
Sintesi a colpo d'occhio
- ZSTD (Zstandard): spesso il miglior bilanciamento per le API quando ti interessa bassa latenza e CPU prevedibile. Buon rapporto senza essere lento.
- Brotli: spesso vince per minori byte sulla rete, specialmente per risposte molto testuali (JSON, contenuti simili a HTML). I livelli alti possono costare più CPU.
- GZIP: l'opzione “funziona ovunque”. Ampiamente supportato e facile da operare, ma tipicamente più lento e/o più grande rispetto alle alternative moderne a pari budget di CPU.
Punti di forza tipici (e cosa significano per le API)
Velocità di ZSTD: ottima quando la tua API è sensibile alla latenza di tail o i server sono CPU‑bound. Può comprimere abbastanza velocemente che l'overhead spesso è trascurabile rispetto al tempo di rete—specialmente per risposte JSON di dimensioni medio‑grandi.
Rapporto di Brotli: migliore quando la banda è la priorità (client mobile, egress costoso, distribuzione via CDN) e le risposte sono per lo più testuali. Ridurre anche pochi KB può valere la pena se puoi permetterti CPU extra.
Compatibilità di GZIP: utile quando hai bisogno del massimo supporto client con minimo rischio di negoziazione (SDK vecchi, client embedded, proxy legacy). È una baseline sicura anche se non è la migliore.
Cosa cambia davvero il “livello di compressione”
I “livelli” di compressione sono preset che scambiano tempo CPU per output più piccolo:
- Livelli bassi: compressione più veloce, payload più grandi. Buoni per API in tempo reale.
- Livelli alti: payload più piccoli, compressione più lenta (e a volte più memoria). Meglio per risposte grandi e cacheabili.
La decompressione è di solito molto più economica della compressione per tutti e tre, ma livelli molto alti possono comunque aumentare il costo client—importante per mobile.
Regola pratica semplice
- Scelta predefinita: usa ZSTD per la maggior parte delle API JSON/REST/GraphQL dove la latenza conta.
- Passa a Brotli: quando stai ottimizzando per byte minimi (risposte testuali, distribuzione CDN, reti lente) e puoi permetterti più CPU.
- Rimani su GZIP: quando ti serve ampia compatibilità o la tua infrastruttura non supporta codifiche più recenti.
Rapporto di compressione vs latenza: il trade‑off fondamentale
La compressione è spesso venduta come “risposte più piccole = API più veloci”. Questo è spesso vero su reti lente o costose—ma non automaticamente. Se la compressione aggiunge abbastanza tempo CPU al server, la richiesta può diventare più lenta nonostante meno byte in rete.
Dove va il tempo
È utile separare due costi:
- Tempo di compressione (lato server): lavoro fatto prima che il server possa iniziare a inviare byte. Questo può aggiungere direttamente al tempo di risposta (TTFB).
- Tempo di decompressione (lato client): lavoro fatto dopo aver ricevuto i byte. Di solito più economico della compressione, ma può pesare su dispositivi poco potenti o client ad alto throughput.
Un alto rapporto di compressione può ridurre il tempo di trasferimento, ma se la compressione aggiunge (per esempio) 15–30 ms di CPU per risposta, potresti perdere più tempo di quello che risparmi—soprattutto su connessioni veloci.
La trappola della latenza di tail sotto carico
Sotto carico, la compressione può peggiorare la p95/p99 più che la p50. Quando l'uso CPU sale, le richieste attendono in coda. La coda amplifica piccoli costi per richiesta in grandi ritardi—la latenza media può sembrare ok, ma gli utenti più lenti ne soffrono.
Misuralo come una feature di performance
Non indovinare. Fai un test A/B o un rollout graduale e confronta:
- p50 e p95 (idealmente p99)
- Utilizzo CPU e saturazione delle istanze API
- Dimensioni delle risposte e TTFB
Testa con pattern di traffico e payload realistiche. Il livello di compressione “migliore” è quello che riduce il tempo totale, non solo i byte.
Costi CPU e memoria su server e client
La compressione non è “gratis”—sposta lavoro dalla rete alla CPU e alla memoria su entrambe le estremità. Nelle API, questo si traduce in tempo di gestione richieste più alto, footprint di memoria maggiore e talvolta rallentamenti client.
Dove si spende la CPU
La maggior parte della CPU viene spesa compressendo le risposte. La compressione trova pattern, costruisce stati/dizionari e scrive l'output codificato.
La decompressione è tipicamente più economica, ma comunque rilevante:
- I server possono decomprimere le richieste (raro per JSON API, più comune per upload o batch di eventi).
- I client decomprimono le risposte sul percorso critico prima di parsare il JSON.
Se la tua API è già CPU‑bound (server applicativi occupati, auth pesante, query costose), attivare un livello alto di compressione può aumentare la latenza di tail anche se i payload si riducono.
Considerazioni sulla memoria
La compressione può aumentare l'uso di memoria in vari modi:
- Buffer: le implementazioni possono richiedere buffer input/output; payload più grandi implicano buffer più grandi.
- Buffering completo vs streaming: la compressione in streaming può iniziare a inviare prima e mantenere la memoria più bassa, mentre il buffering completo può gonfiare il picco di memoria per richiesta.
In ambienti containerizzati, picchi di memoria più alti possono tradursi in OOM kills o limiti più stretti che riducono la densità.
Impatto su autoscaling e limiti container
La compressione aggiunge cicli CPU per risposta, riducendo il throughput per istanza. Questo può far scattare l'autoscaling prima, aumentando i costi. Un pattern comune: la banda cala, ma il consumo CPU sale—quindi la scelta giusta dipende da quale risorsa è scarsa per te.
Perché la velocità di decompressione conta per i client
Su mobile o dispositivi a bassa potenza, la decompressione compete con rendering, esecuzione JavaScript e batteria. Un formato che fa risparmiare pochi KB ma impiega più tempo a decomprimere può risultare più lento, in particolare quando conta il “tempo per dati utilizzabili”.
ZSTD per API: punti di forza, limiti e valori predefiniti sensati
Zstandard (ZSTD) è un formato moderno progettato per offrire un buon rapporto di compressione senza rallentare l'API. Per molte API ricche di JSON è una solida “default”: risposte visibilmente più piccole di GZIP a latenza simile o inferiore, più decompressione molto veloce sui client.
Dove ZSTD eccelle
ZSTD è più utile quando ti interessa il tempo end‑to‑end, non solo i byte minimi. Tende a comprimere rapidamente e decomprimere estremamente velocemente—utile per API dove ogni millisecondo di CPU compete con la gestione della richiesta.
Funziona bene su un ampio range di dimensioni payload: JSON piccoli‑medi vedono guadagni significativi, mentre risposte grandi possono beneficiare ancora di più.
Livelli di compressione sensati per API
Per la maggior parte delle API, inizia con livelli bassi (comuni 1–3). Spesso offrono il miglior compromesso latenza/size.
Usa livelli più alti solo quando:
- I payload sono grandi (centinaia di KB o MB)
- La banda è costosa o limitata
- Hai misurato che la CPU non è il collo di bottiglia
Un approccio pragmatico è un default globale basso, poi aumentare selettivamente il livello per alcuni endpoint con risposte grandi.
Streaming e modalità dizionario
ZSTD supporta lo streaming, che può ridurre la memoria di picco e iniziare a inviare dati prima per risposte grandi.
La modalità dizionario può dare grandi vantaggi per API che tornano molti oggetti simili (chiavi ripetute, schemi stabili). È più efficace quando:
- I payload sono relativamente piccoli ma frequenti
- Puoi gestire dizionari versionati in modo sicuro
Limiti di compatibilità da tenere d'occhio
Il supporto server è semplice in molti stack, ma la compatibilità client può essere il fattore decisivo. Alcuni client HTTP, proxy e gateway non annunciano o non accettano Content-Encoding: zstd di default.
Se servi consumatori terzi, mantieni un fallback (di solito GZIP) ed abilita ZSTD solo quando Accept-Encoding lo include chiaramente.
Brotli per API: quando vince e quando no
Brotli è progettato per comprimere molto bene il testo. Su JSON, HTML e altri payload “verbosi”, spesso supera GZIP sul rapporto di compressione—specialmente a livelli alti.
Dove Brotli vince
Le risposte molto testuali sono il punto forte di Brotli. Se l'API invia grandi documenti JSON (cataloghi, risultati di ricerca, blob di configurazione), Brotli può ridurre i byte in modo significativo, utile su reti lente e per ridurre costi di egress.
Brotli è anche forte quando puoi comprimere una volta e servire molte volte (risposte cacheabili, risorse versionate). In questi casi, Brotli ad alto livello può valere la pena perché il costo CPU si ammortizza.
Dove Brotli delude
Per risposte API dinamiche (generate ad ogni richiesta), i migliori rapporti di Brotli spesso richiedono livelli alti che possono essere costosi in CPU e aggiungere latenza. Una volta considerato il tempo di compressione, il vantaggio reale su ZSTD (o anche su GZIP ben configurato) può essere più piccolo del previsto.
È anche meno convincente per payload che non si comprimono bene (dati già compressi, molti formati binari). In quei casi consumi CPU inutilmente.
Indicazioni pratiche sui livelli
- Compressione a runtime: usa livelli bassi (comuni 1–4) per evitare spike di CPU.
- Precompressed/statico: livelli più alti (spesso 8–11) possono valere la pena quando ammortizzati su molte richieste.
Note sul supporto client
I browser generalmente supportano bene Brotli su HTTPS, ecco perché è popolare per il traffico web. Per client API non browser (SDK mobile, dispositivi IoT, stack HTTP più vecchi), il supporto può essere inconsistenti—quindi negozia correttamente con Accept-Encoding e mantieni un fallback (tipicamente GZIP).
GZIP per API: compatibilità e performance pratiche
GZIP resta la risposta predefinita perché è l'opzione più universalmente supportata. Quasi tutti i client HTTP, browser, proxy e gateway capiscono Content-Encoding: gzip, e quella prevedibilità conta quando non controlli completamente cosa c'è tra il server e gli utenti.
Perché rimane comune
Il vantaggio non è che GZIP sia “migliore”—è che raramente è la scelta sbagliata. Molte organizzazioni hanno anni di esperienza operativa con esso, default sensati nei web server e meno sorprese con intermediari che potrebbero gestire male codifiche più nuove.
Livelli pratici per API
Per payload API (spesso JSON), livelli medio‑bassi sono il sweet spot. Livelli come 1–6 spesso danno la maggior parte della riduzione della dimensione mantenendo CPU ragionevole.
Livelli molto alti (8–9) possono spremere qualcosina in più, ma il tempo CPU aggiuntivo di solito non vale per traffico dinamico dove la latenza conta.
Come si confronta sulle CPU moderne
Su hardware moderno, GZIP è generalmente più lento di ZSTD a rapporti di compressione simili, e spesso non raggiunge i migliori rapporti di Brotli su testo. Nei workload reali di API questo spesso significa:
- ZSTD vince spesso su rapporto velocità/byte_risparmiati.
- Brotli può vincere sulle dimensioni per testo altamente comprimibile, ma può costare più CPU a seconda delle impostazioni.
- GZIP resta competitivo perché è "abbastanza veloce" ed è altamente ottimizzato negli stack.
Edge case di compatibilità (client e intermediari vecchi)
Se devi supportare client vecchi, dispositivi embedded, proxy aziendali rigidi o gateway legacy, GZIP è la scelta più sicura. Alcuni intermediari possono rimuovere codifiche sconosciute, non passarle o interrompere la negoziazione—problemi meno comuni con GZIP.
Se il tuo ambiente è misto o incerto, partire da GZIP (e aggiungere ZSTD/Brotli solo dove controlli l'intero percorso) è spesso la strategia di rollout più affidabile.
Tipi di payload: cosa si comprime bene (e cosa no)
I guadagni dalla compressione non dipendono solo dall'algoritmo. Il fattore più importante è il tipo di dati che invii. Alcuni payload si riducono molto con ZSTD, Brotli o GZIP; altri quasi per nulla e consumano solo CPU.
Candidati ideali (alto ritorno)
Le risposte testuali tendono a comprimersi estremamente bene perché contengono chiavi ripetute, spazi e pattern prevedibili.
- JSON (incluse risposte REST tipiche)
- GraphQL (spesso verboso con nomi di campo ripetuti)
- XML e HTML
- Grandi log di testo e stack traces restituiti dalle API
In generale, più ripetizione e struttura, migliore il rapporto di compressione.
Payload binari: “forse” (misura prima)
Formati binari come Protocol Buffers e MessagePack sono più compatti del JSON, ma non sono “casuali”. Possono comunque contenere tag ripetuti, schemi simili e sequenze prevedibili.
Questo significa che spesso sono ancora comprimibili, soprattutto per risposte grandi o endpoint con liste. La risposta affidabile è testare con traffico reale: stesso endpoint, stessi dati, compressione on/off e confronta dimensione e latenza.
Di solito non vale la pena (già compressi)
Molti formati sono già compressi internamente. Applicare compressione HTTP sopra di essi in genere dà risparmi trascurabili e può aumentare il tempo di risposta.
- Immagini: JPEG, PNG, WebP
- Video/audio: MP4 (e simili)
- Archivi: ZIP, file gzip
- PDF: spesso usa già compressione
Per questi è comune disabilitare la compressione per tipo di contenuto.
Euristiche pratiche (semplice da mantenere)
Un approccio semplice è comprimere solo quando le risposte superano una dimensione minima.
- Imposta una soglia minima (per esempio, qualche KB) prima di abilitare
Content-Encoding. - Comprimi sempre risposte testuali grandi; valuta di saltare la compressione per JSON piccoli dove gli header dominano.
Questo mantiene la CPU concentrata sui payload dove la compressione davvero riduce banda e migliora le performance end‑to‑end.
Intestazioni HTTP e negoziazione: farlo correttamente
La compressione funziona bene solo quando client e server concordano un encoding. Questo avviene tramite Accept-Encoding (inviato dal client) e Content-Encoding (inviato dal server).
Accept-Encoding e Content-Encoding (semplici esempi)
Un client pubblicizza cosa può decodificare:
GET /v1/orders HTTP/1.1
Host: api.example
Accept-Encoding: zstd, br, gzip
Il server sceglie uno e dichiara cosa ha usato:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: zstd
Se il client invia Accept-Encoding: gzip e rispondi con Content-Encoding: br, quel client potrebbe non riuscire a parsare il corpo. Se il client non invia Accept-Encoding, il comportamento più sicuro è non comprimere.
Ordine di priorità lato server
Un ordine pratico per le API è spesso:
zstdprima (ottimo equilibrio velocità/rapporto)- poi
br(spesso più piccolo, a volte più lento) - poi
gzip(massima compatibilità)
In altre parole: zstd > br > gzip.
Non considerarlo universale: se il tuo traffico è per lo più browser, br potrebbe avere priorità più alta; se hai client mobile vecchi, gzip potrebbe essere la scelta più sicura.
Domande frequenti
Quando vale davvero la pena abilitare la compressione delle risposte API?
Usa la compressione delle risposte quando le risposte sono ricche di testo (JSON/GraphQL/XML/HTML), di dimensioni medio‑grandi e i tuoi utenti sono su reti lente/costose o sostieni costi significativi di egress. Evitala (o usa una soglia alta) per risposte piccole, media già compressa (JPEG/MP4/ZIP/PDF) e servizi CPU‑bound dove lavoro aggiuntivo per richiesta peggiorerebbe p95/p99.
Perché la compressione può rendere un'API più lenta anche se le risposte sono più piccole?
Perché scambia larghezza di banda con CPU (e a volte memoria). Il tempo di compressione può ritardare l'inizio dell'invio dei byte (TTFB) e, sotto carico, amplificare la coda delle richieste—spesso peggiorando la latenza di tail anche se la latenza media migliora. La configurazione “migliore” è quella che riduce il tempo end‑to‑end, non solo le dimensioni dei payload.
Come dovrei scegliere tra ZSTD, Brotli e GZIP?
Una priorità pratica per molte API è:
zstdprima (veloce, buon rapporto)- poi
br(spesso la più piccola per testo, può costare più CPU) - poi
gzip(compatibilità più ampia)
Basati sempre su ciò che il client annuncia in Accept-Encoding e mantieni un fallback sicuro (di solito gzip o identity).
Quali livelli di compressione sono sensati per risposte API dinamiche?
Parti dal basso e misura.
- ZSTD: livello 1–3 (o fino a 3–5) per la maggior parte delle API JSON dinamiche
- Brotli: livello 1–4 per la compressione a runtime; riserva 8–11 per contenuti precompressi/statici
- GZIP: livello 5–6 come buon default
I livelli più alti danno solitamente guadagni di dimensione decrescenti ma possono far salire la CPU e peggiorare p95/p99.
Dovrei comprimere ogni risposta o solo sopra una certa dimensione?
Usa una soglia minima di dimensione per non consumare CPU su payload minuscoli.
- Punto di partenza tipico: 1–2 KB
- Se sei CPU‑bound o molto “chatty”: considera 4 KB
Regola per endpoint confrontando bytes risparmiati vs tempo server aggiunto e l'impatto su p50/p95/p99.
Quali tipi di payload si comprimono bene (e quali di solito no)?
Concentrati su tipi di contenuto strutturati e ripetitivi:
- Ottimi: JSON, GraphQL, XML, HTML, grandi log testuali
- “Forse”: Protobuf/MessagePack (spesso comprimibili—misura)\n- Di solito non vale la pena: JPEG/PNG/WebP, MP4, ZIP/gz, molti PDF
Una pratica comune è abilitare la compressione solo per Content-Type testuali e disabilitarla per formati già compressi.
Come funzionano Accept-Encoding e Content-Encoding per le API?
La compressione deve seguire la negoziazione HTTP:
- Il client invia
Accept-Encoding(per es.,zstd, br, gzip) - Il server risponde con un
Content-Encodingsupportato
Se il client non invia Accept-Encoding, la risposta più sicura è tipicamente nessuna compressione. Non restituire mai un Content-Encoding che il client non ha annunciato, altrimenti rischi errori nel parsing del corpo.
Perché `Vary: Accept-Encoding` è importante quando si usa la compressione?
Aggiungi:
Vary: Accept-Encoding
Questo evita che CDN/proxy memorizzino una variante compressa (es. gzip) e la servano a un client che non l'ha richiesta o non la può decodificare (o per zstd/br). Se supporti più codifiche, questa intestazione è essenziale per la correttezza della cache.
Quali sono i bug di compressione più comuni in produzione?
I guasti comuni includono:
- Doppia compressione (l'origine comprime e poi il gateway/CDN ricomprime)
- Mismatch header/body (
Content-Encodingdichiara gzip ma il corpo non è compresso) - Negoziazione errata (ignorare
Accept-Encoding) - Interferenze di proxy/CDN (rimozione o modifica delle intestazioni)
Content-Lengtherrato quando si streamma/comprime
Per il debug, cattura intestazioni raw e verifica la decompressione con un client/strumento noto funzionante.
Come dovrei fare rollout e monitorare la compressione API in sicurezza?
Tratta il rollout come una feature di performance:
- Canary o piccola fetta iniziale, poi aumento (es. 1% → 5% → 25% → 100%)
- Mantieni un rollback rapido (feature flag o configurazione gateway)
- Monitora:
- Utilizzo/saturazione CPU
- Latenze p50/p95/p99 e TTFB
- Bytes sulla rete (compressi vs non compressi)
- Errori/timeout e fallimenti di decodifica client
Se la latenza di tail cresce sotto carico, abbassa il livello, aumenta la soglia o passa a un codec più veloce (spesso ZSTD).