Verkeerd geconfigureerd HTTP-compressie bespaart zelden tijd en veroorzaakt vaak nieuwe problemen. Ik laat concreet zien hoe verkeerde niveaus, ontbrekende headers en een onduidelijke compressielocatie de TTFB omhoog drijven, monitoringalarmen activeren en uiteindelijk gebruikers vertragen.
Centrale punten
- Niveaus onderscheid maken: matig on-the-fly, hoog bij pre-compressie
- Typen correct: tekst comprimeren, afbeeldingen niet
- Scheiding statisch versus dynamisch, eerst caching
- Kop netjes: Vary en Accept‑Encoding
- Controle met TTFB, CPU en vitale functies
Waarom verkeerde instellingen meer kwaad dan goed doen
Compressie werkt als een eenvoudige schakelaar, maar hoge CPU-kosten kunnen elk voordeel tenietdoen. Als ik Brotli met niveau 9-11 instel op dynamische antwoorden, verleng ik de servertijd en verslechter ik de TTFB aanzienlijk. Vooral bij HTML-weergaven of API-responses leidt dit tot trage weergave en frustreert het gebruikers. Monitoring meldt dan vermeende storingen omdat eindpunten traag reageren of met verkeerde coderingen. Ik behandel compressie daarom als een prestatiefunctie die ik moet kalibreren in plaats van blindelings te activeren.
De juiste prioriteiten stellen: de payload verlagen zonder TTFB-schade
Ik verminder eerst de laadvermogen render-kritische tekstbronnen en let tegelijkertijd op de latentie. Brotli levert bij tekstbestanden vaak 15-21 % kleinere payloads dan Gzip, maar het voordeel is alleen de moeite waard als de CPU-tijd binnen de perken blijft. Bij dynamische reacties begin ik conservatief, meet ik TTFB en pas ik niveaus in kleine stappen aan. Pure tekstbestanden in de cache winnen constant, terwijl te sterke stappen on-the-fly het tegenovergestelde effect hebben. Het doel blijft een snelle levering van de eerste byte en een snelle First Contentful Paint op echte apparaten.
Veelvoorkomende verkeerde configuraties en hun bijwerkingen
Te hoog Niveaus voor dynamische inhoud zorgen voor CPU-pieken, blokkeren flush-punten en vertragen het renderen aanzienlijk. Onjuist onderhouden inhoudstypelisten laten CSS, JS, JSON of SVG ongecomprimeerd, terwijl reeds gecomprimeerde afbeeldingen zinloos rekenkracht verspillen. Als er geen scheiding is tussen statisch en dynamisch, comprimeert de server assets telkens opnieuw en verspilt hij middelen. Zonder Vary: Accept-Encoding komen gemengde varianten in de cache terecht, wat leidt tot onleesbare antwoorden voor clients zonder de juiste codering. In ketens met proxy of CDN ontstaan bovendien dubbele compressie, decompressie op de verkeerde hop en inconsistente headers, die moeilijk te reproduceren zijn.
Gzip versus Brotli: een praktische beslissing
Ik gebruik Broodstengel voor statische tekstbestanden met een hoog niveau en houd dynamische antwoorden op een gemiddeld niveau. Voor HTML en JSON on-the-fly kies ik Brotli 3-4 of Gzip 5-6, omdat de verhouding tussen gegevensgrootte en CPU-tijd meestal goed is. Vooraf gecomprimeerde CSS/JS/lettertypen pak ik in met Brotli 9-11 en lever ik ze vanuit de cache of CDN. Als er geen clientondersteuning is, valt de server netjes terug op Gzip of ongecomprimeerd. Wie een meer diepgaande vergelijking wil maken, vindt een compact overzicht op Brotli versus Gzip, inclusief effecten op tekstbronnen.
| Type inhoud | Procedure | Level on-the-fly | Niveau pre-compressie | Tip |
|---|---|---|---|---|
| HTML (dynamisch) | Brotli of Gzip | Br 3–4 / Gz 5–6 | niet gebruikelijk | Flush-punten instellen, TTFB meten |
| JSON-API's | Brotli of Gzip | Br 3–4 / Gz 5–6 | niet gebruikelijk | Houd de koptekst consistent |
| CSS/JS (statisch) | Brotli heeft de voorkeur | geen | Br 9–11 | vooraf gecomprimeerd cachen |
| SVG/lettertypen | Brotli heeft de voorkeur | geen | Br 9–11 | Range-verzoeken controleren |
Grenswaarden: minimumgroottes, kleine antwoorden en drempels
Compressie is pas zinvol vanaf een bepaalde minimale grootte. Zeer kleine HTML-fragmenten of 1-2 kB JSON worden zelfs iets groter door header-overhead of het initialiseren van het woordenboek. Daarom stel ik een ondergrens in (bijvoorbeeld 512-1024 bytes) waaronder de server ongecomprimeerd reageert. Tegelijkertijd beperk ik te grote objecten: meerdere megabytes tekst met een hoog niveau blokkeren workers voor lange tijd. In de praktijk helpen twee instellingen: gzip_min_length of gelijkwaardige schakelaars en limieten voor buffers om OOM-risico's te verminderen.
MIME-typen en herkenning: Content-Type correct onderhouden
Wat als Tekst geldt – gestuurd via MIME-typen. Ik houd de lijst expliciet en vermijd jokertekens. Typische kandidaten: text/html, tekst/css, application/javascript, application/json, image/svg+xml, application/xml, tekst/plain. Niet comprimeren: image/* (JPEG/PNG/WebP/AVIF), application/zip, application/pdf, font/woff2, application/wasm. Correcte Contenttype-headers zijn cruciaal om ervoor te zorgen dat de engine betrouwbare beslissingen neemt en niet hoeft te snuffelen.
Statisch versus dynamisch: duidelijke scheiding en caching
Ik scheiden statisch en dynamisch duidelijk, zodat de CPU niet voortdurend dezelfde bytes opnieuw hoeft te verpakken. Statische assets comprimeer ik in de build of aan de rand en lever ze vanuit een cache met een lange looptijd. Dynamische antwoorden comprimeer ik matig en zorg ervoor dat kritieke delen vroeg worden verzonden. Zo profiteert de gebruiker direct van de eerste bytes, terwijl grote tekstblokken achteraan blijven doorstromen. Hoe minder vaak ik inhoud opnieuw genereer, hoe rustiger de belastingscurve blijft.
HTTP/2 en HTTP/3: compressie zonder blokkades
Multiplexing verandert de Prioriteiten: Veel kleine, goed gecomprimeerde tekstbestanden via één verbinding zorgen voor snelheid, maar een trage on-the-fly-compressie kan meerdere streams tegelijk vertragen. Ik stel flush-punten zo in dat de browser vroeg begint met renderen. Headers, kritieke CSS en de eerste HTML-bytes moeten onmiddellijk worden verzonden, waarna de rest gecomprimeerd volgt. Wie de interactie nader wil bekijken, vindt achtergrondinformatie op HTTP/2-multiplexing. Kleine aanpassingen aan buffergroottes en compressievensters hebben vaak een merkbaar effect.
Proxies, loadbalancers, CDN: de juiste plek om te comprimeren
In ketens met Proxy en CDN bepaal ik waar precies gecomprimeerd wordt en houd ik me daar strikt aan. Dubbele compressie of decompressie op de verkeerde hop vernietigt voordelen en verwart caches. Idealiter comprimeert de edge voor statische tekstassets, terwijl de backend dynamische antwoorden gematigd on-the-fly levert. Als een client geen Brotli accepteert, komt Gzip of Plain terug, duidelijk gesignaleerd via Vary: Accept-Encoding. Voor een efficiënte levering helpt de handleiding voor CDN-optimalisatie met duidelijke cachingregels en consistente varianten.
Build-pijplijn: betrouwbaar beheer van pre-compressie
Vooraf gecomprimeerde bestanden hebben Discipline bij de levering. Naast .css/.js ook .css.br en .css.gz (analoog voor JS/SVG/TTF) in de build. De server selecteert op basis van Accept-Encoding de juiste variant en stelt Contentcodering, Contenttype, Content‑Length consistent. Belangrijk: geen dubbele compressie, geen verkeerde lengtes. ETags en checksums zijn variantgerelateerd – ik accepteer verschillende ETags per codering of gebruik zwakke ETags. Ik test range-verzoeken afzonderlijk, zodat byte-ranges bij .br-Assets correct worden bediend.
Header-details: lengte, caching, hervalidatie
Bij on-the-fly-compressie stuur ik vaak Transfercodering: chunked in plaats van een vaste Content‑Length. De client kan hiermee omgaan; het wordt pas kritisch wanneer een downstream-instantie ten onrechte een vaste lengte toevoegt. In cachinglagen let ik erop dat Variëren‑header de Compressievarianten scheiden en Cachebeheer redelijke TTL's opgeeft. Voor statische assets zijn lange TTL's met een duidelijke versiebeheer (bijv. hash in de bestandsnaam) ideaal, dynamische antwoorden krijgen korte TTL's of no‑store, afhankelijk van de gevoeligheid. Laatst gewijzigd en If-None-Match helpen om revalidaties efficiënt te houden – per coderingsvariant.
Streaming, flush en serverbuffer
Voor snelle Waargenomen prestaties Ik verstuur vroeg: HTML-head, kritische CSS en eerste markup-bytes worden onmiddellijk verzonden, daarna volgt de gecomprimeerde romp. Serverside buffers (bijv. proxy-buffers, app-framework-buffers) mogen dit niet vertragen. Voor server-sent events of chatachtige streams controleer ik of compressie zinvol is: ASCII-events profiteren ervan, maar te agressieve buffering vernietigt het live-effect. Indien nodig deactiveer ik proxy-buffering en stel ik gematigde niveaus in, zodat heartbeats en kleine events niet blijven hangen.
Vary-header, onderhandeling en „http compression errors“
De juiste VariërenDe Accept-Encoding-header bepaalt of caches de juiste varianten leveren. Ik verstuur Vary: Accept-Encoding consequent mee bij gecomprimeerde inhoud en voorkom zo fouten. Monitoring markeert doelen graag als „down“ wanneer headers inconsistent zijn of dubbele coderingen voorkomen. Als dit sporadisch voorkomt, bekijk ik paden via proxy-hops en regio's afzonderlijk. Testtools voor Gzip/Brotli helpen me om headers en payloads duidelijk te begrijpen.
Beveiliging: compressie en vertrouwelijke gegevens
Compressie kan in combinatie met TLS in bepaalde patronen zijkanaalaanvallen bevorderen. Daarom controleer ik antwoorden die zowel gevoelige formuliergegevens als door aanvallers gestuurde inhoud bevatten. Als de omvang kan worden gevarieerd, verminder ik de compressie of isoleer ik inhoud. Vaak volstaat het om specifieke paden zonder compressie of zonder dynamische mix te leveren. Veiligheid gaat voor een paar bespaarde kilobytes.
Meetstrategie: TTFB, CPU, Core Web Vitals
Ik beoordeel TTFB, FCP en LCP parallel aan CPU-tijd per worker en bytes per verzoek. Ik test wijzigingen in niveaus of procedures op een gecontroleerde manier en vergelijk varianten. Het is belangrijk om een duidelijke scheiding te maken tussen soorten bronnen, omdat HTML, JSON en CSS/JS zich anders gedragen. Real User Monitoring bevestigt of echte apparaten hiervan profiteren. Als de belasting of het aantal fouten toeneemt, draai ik de wijziging snel terug.
Tuning-workflow: zo ga ik stap voor stap te werk
Om te beginnen activeer ik alleen gematigde Niveaus voor dynamische antwoorden en laat statische assets vooraf verpakken. Vervolgens controleer ik headers op correcte onderhandeling en voeg ik Vary: Accept-Encoding toe. Daarna meet ik TTFB en CPU tijdens piekbelasting, pas ik niveaus in kleine stappen aan en controleer ik opnieuw. In de volgende stap stel ik flush-punten in voor vroege HTML-onderdelen, zodat de browser eerder rendert. Ten slotte controleer ik CDN- en proxy-hops op dubbele compressie en houd ik de verantwoordelijkheden duidelijk.
Foutmeldingen in de praktijk: symptomen, oorzaken, oplossing
Typisch „http-compressiefouten“ herken ik aan terugkerende patronen:
- Dubbele compressie:
Content‑Encoding: gzip, gzipof vreemde binaire tekens in de HTML. Oorzaak: upstream comprimeert al, downstream comprimeert opnieuw. Oplossing: slechts één instantie verantwoordelijk maken.,ContentcoderingControleer, respecteer pre-compressie. - Verkeerde lengte:
Content‑Lengthpast niet bij het gecomprimeerde antwoord, clients breken af. Oorzaak: lengte vóór compressie berekend. Oplossing: lengte weglaten (Chunked) of na compressie correct instellen. - Gemengde varianten in de cache: Gzip-bytes naar clients zonder ondersteuning. Oorzaak: ontbrekende
Vary: Accept-Encoding. Fix: Vary instellen en cache leegmaken. - Time-outs/hoge TTFB: Compressie blokkeert werknemers, geen vroege flush-bytes. Oplossing: niveau verlagen, flush-punten instellen, CPU-budget per verzoek beperken.
- „Onbekende inhoudscodering“: Oudere proxies verwijderen headers of accepteren
brNiet. Oplossing: zorg voor een fallback naar Gzip, configureer Edge voor incompatibele hops.
Tests en diagnose: snel en betrouwbaar controleren
Ik begin met eenvoudige header-controles: curl -sI -H "Accept-Encoding: br,gzip" https://example.org/ moet Contentcodering en Variëren tonen. Daarna laad ik de bron zonder en met Accept-Encoding en bytes vergelijken. DevTools in de browser geven de grootte weer via leiding vs. na decompressie. Onder belasting test ik varianten afzonderlijk (p50/p95/p99), omdat compressiekosten niet lineair schalen. Belangrijk: tests via echte paden (incl. CDN/proxyketen), niet alleen direct bij de oorsprong.
Server- en framework-valkuilen
Op app-niveau zijn Middleware vaak te snel geactiveerd. Ik gebruik ze alleen als er geen upstream reverse proxy is die comprimeert. In PHP-stacks vermijd ik zlib.output_compression parallel aan Nginx/Apache-compressie. In Node/Express beperk ik de middleware tot tekstuele routes en stel ik een minimumgrootte in. Java-stacks met filters (bijv. GzipFilter) krijgen uitzonderingen voor binaire formaten. Algemeen: slechts één compressielaag actief, duidelijke verantwoordelijkheid.
Wat niet (of slechts zelden) comprimeren
Veel formaten zijn al gecomprimeerd of reageren slecht: WOFF2-lettertypen, WebP/AVIF, MP4, PDF, ZIP, WASM. Ook binaire protocollen zoals Protobuf of Parquet leveren nauwelijks voordelen op. SVG is tekst en profiteert ervan, maar ik controleer dit nog. Range-verzoeken voor sprongmarkeringen in documenten. Voor afbeeldingen vermijd ik decompressie in tussenstappen: Eenmaal gecomprimeerd blijft gecomprimeerd.
API's en gegevens: optimaliseer de structuur in plaats van het niveau
Bij JSON-API's brengen gestructureerde optimalisaties Meer dan alleen level-orgieën: verwijder onnodige velden, gebruik getallen in plaats van strings, geen overmatige pretty-opmaak in productie. Kompas: als het antwoord na Gzip/Brotli nog steeds veel kilobytes „lucht“ bevat, is een schema-dieet de moeite waard. Voor GraphQL/REST kan server-side batching het aantal gecomprimeerde antwoorden verminderen.
Bedrijf en capaciteitsplanning
Compressie is CPU-werk. Ik plan Budgetten per worker/pod en beperk gelijktijdige compressietaken. Onder belasting schaal ik horizontaal en houd ik het niveau stabiel, in plaats van op te voeren tijdens pieken. In het CDN let ik op regio-pariteit: Brotli aan de rand ontlast de oorsprong enorm. Ik kalibreer waarschuwingen op P95/99 van TTFB en CPU-verzadiging, niet alleen op gemiddelde waarden.
Checklist voor stabiele HTTP-compressie
- Matige niveaus voor dynamische reacties, hoge niveaus alleen voor pre-compressie
- MIME-typenlijst expliciet onderhouden, afbeeldingen/binaire formaten uitsluiten
- Statisch versus dynamisch scheiden, pre-compressie in build/edge
- Vary: Accept-Encoding altijd meesturen, consistente ETag/cache-header
- Minimale grootte en bufferlimieten instellen, bereikverzoeken testen
- Flush-punten plaatsen, proxy/app-buffering in de gaten houden
- Slechts één hop gecomprimeerd, zorg voor fallback naar Gzip/Plain
- TTFB, CPU en vitale functies meten, p95/p99 bekijken, wijzigingen stapsgewijs doorvoeren
- Controleer specifiek op foutpatronen (dubbele compressie, verkeerde lengte)
Voorbeeldconfiguraties doorlopen in gedachten
Op Apache Ik activeer mod_deflate of mod_brotli, definieer teksttypen expliciet en stel niveaus in afhankelijk van het pad. Voor Nginx gebruik ik gzip-richtlijnen en lever ik vooraf gecomprimeerde .br-bestanden voor statische assets, terwijl brotli_static of een module de edge-variant bedient. IIS scheidt statische en dynamische compressie, wat ik aanvul met CPU-drempels en duidelijke typelijsten. In alle gevallen controleer ik Vary-headers, Content-Encoding en Content-Length op consistentie. Voorbeeldwaarden helpen, maar uiteindelijk telt de meting onder echte belasting.
Kort samengevat
De meest effectieve Strategie voor HTTP-compressie begint conservatief, meet consequent en scheidt statisch van dynamisch. Brotli toont zijn sterke punten bij voorgecomprimeerde tekstbestanden, Gzip of gematigde Brotli houdt dynamische antwoorden slank genoeg. Schone headers, duidelijke verantwoordelijkheden in proxy/CDN-ketens en realistische tests voorkomen „http compression errors“. Ik geef altijd prioriteit aan de vroege levering van kritieke bytes, in plaats van elke laatste procent compressie af te dwingen. Zo levert de site merkbaar sneller, zonder de serverbelasting en foutmeldingen op te drijven.


