Glossary
HTTP compression
HTTP compression shrinks a response before it is sent and has the browser decompress it on arrival. For text — HTML, CSS, JavaScript, JSON, SVG — it typically removes 70 to 80 percent of the bytes, which is the largest single saving available on most sites for the smallest amount of work. It is negotiated per request: the client advertises what it understands, and the server chooses.
How the negotiation works
The client sends `Accept-Encoding` listing the algorithms it supports, in practice `gzip, deflate, br` and increasingly `zstd`.
The server picks one, compresses, and states its choice in `Content-Encoding`.
A `Vary: Accept-Encoding` response header tells caches that the response differs by encoding, without which a cache can serve a compressed body to a client that cannot decompress it.
If the client advertises nothing the server understands, the response is sent uncompressed, which is the correct fallback.
Compression is applied to the body only. Headers are compressed separately by HTTP/2 and HTTP/3 using their own mechanism, which is why a response with many headers costs less than its raw size suggests on a modern connection.
gzip, Brotli and zstd
gzip is universally supported and fast. It remains the safe default and the fallback for everything.
Brotli typically produces files 15 to 20 percent smaller than gzip at comparable settings, and is supported by every current browser over HTTPS.
Brotli's higher compression levels are slow enough to be unsuitable for generating responses on the fly, and ideal for static files compressed once at build time.
The practical configuration is: Brotli at a high level for static assets prepared ahead of time, Brotli at a moderate level or gzip for dynamic responses, gzip as the fallback.
What should not be compressed
Images in modern formats. JPEG, PNG, WebP and AVIF are already compressed, and passing them through gzip costs processing time and typically makes them very slightly larger.
Video and audio, for the same reason.
Fonts in WOFF2 format, which uses Brotli internally. WOFF and older formats do benefit.
Archives and anything already in a compressed container.
SVG is the exception that surprises people: it is text and compresses extremely well, and it is frequently omitted from compression configuration because it is filed mentally with images.
How to check it
`curl -H "Accept-Encoding: gzip, br" -I https://example.com | grep -i content-encoding` shows what the server chose.
Comparing the compressed and uncompressed sizes of the same resource quantifies the saving, and a ratio near 1 means compression is not being applied.
Check every text type, not just HTML. Configurations that compress HTML and omit JSON or SVG are common.
Check behind a CDN as well as at the origin: compression is frequently applied at the edge, and an origin that appears uncompressed may be fine in production.
Watch for a very small response that is not compressed: most servers apply a minimum size threshold below which compression costs more than it saves, and that behaviour is correct rather than a finding.
Frequently asked questions
- Should I use Brotli or gzip?
- Both. Brotli where the client supports it, since it produces smaller files, with gzip as the fallback for clients that do not.
- Should images be gzipped?
- No. Modern image formats are already compressed, so re-compressing costs processing time and saves nothing.
- Why is Vary: Accept-Encoding needed?
- It tells caches the response varies by encoding. Without it a cache can serve a compressed body to a client that did not ask for one.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website