Brotli, gzip and the compression you forgot
Text compression is one of the oldest performance wins on the web, and it is still misconfigured surprisingly often.
Free bytes
HTML, CSS, JavaScript, JSON and SVG are all text, and text compresses extremely well. A typical JavaScript bundle shrinks to a quarter of its size with gzip and slightly smaller still with Brotli. That reduction applies to every visitor on every request, at almost no cost.
And yet audits regularly find sites serving some of their text uncompressed, usually because one route, one file type, or one origin was configured differently from the rest.
Gzip versus Brotli
Gzip is universally supported and fast at every compression level. Brotli typically produces files 15 to 20 percent smaller for text, and all modern browsers support it over HTTPS.
The tradeoff is compression speed. Brotli at its highest levels is slow, too slow to run on every dynamic response. The common approach:
- Static assets: precompress with Brotli at the highest level during the build, and serve the precompressed file.
- Dynamic responses: compress on the fly with Brotli at a moderate level, or with gzip.
Check what you actually serve
Request each type of resource with an Accept-Encoding header and inspect the Content-Encoding of the response. Look specifically at:
- HTML from server-rendered routes.
- JSON from API endpoints the page calls.
- Fonts in older formats, which compress well, and WOFF2, which does not need it.
- SVG files, which are often forgotten.
- Responses from third-party origins you control, such as an image or API subdomain.
Do not compress what is already compressed
JPEG, PNG, WebP, AVIF, WOFF2, and video are already compressed. Running them through gzip wastes CPU and can make them very slightly larger. Most servers skip these types by default, but custom configurations sometimes do not.
The Vary header
When a response can be served in different encodings, it must carry Vary: Accept-Encoding. Without it, a cache may store the Brotli version and serve it to a client that only understands gzip, which will display garbage. Most CDNs handle this automatically, but it is worth confirming.
Small responses
Compression has overhead. Responses under a kilobyte or so gain little and are often left uncompressed. That is fine; the important thing is that large text responses are always compressed.
A five-minute check
Open your site with developer tools, filter the network panel to text resources, and add the content encoding column. Anything large without an encoding listed is a quick, safe win.