Website problems

No text compression

HTTP compression encodes a response before sending it, and the browser decodes it on arrival. For text — HTML, CSS, JavaScript, SVG, JSON — gzip typically reduces the transferred size by around 70%, and Brotli does better again. It is negotiated automatically: the browser advertises what it supports in the `Accept-Encoding` header and the server chooses. Serving text uncompressed therefore sends roughly three times the necessary bytes to every visitor, and enabling it is a server configuration change rather than a change to the site.

How the negotiation works

The browser sends `Accept-Encoding: gzip, deflate, br, zstd`, listing what it can decode.

The server picks one, compresses the response, and states its choice in `Content-Encoding`. If it picks nothing, the response is sent as-is and no header appears.

Every browser in current use supports gzip, and all current major browsers support Brotli over HTTPS. There is no compatibility reason to serve text uncompressed.

Brotli generally produces smaller output than gzip for the same content, at a higher compression cost — which matters for dynamic responses and not at all for static files compressed once at build time.

The decompression cost on the client is negligible compared with the transfer time saved, including on low-end devices.

Why it is so often missing

It is a server setting, so it lives outside the application and outside anyone's code review. Nobody's pull request turns it off; nobody's pull request turns it on either.

A CDN in front of the origin usually compresses by default, which means the problem disappears for cached responses and persists for uncached ones — so it is intermittent and hard to notice.

Compression frequently applies to a default list of MIME types that omits the ones a modern site uses: `application/json`, `image/svg+xml`, `application/manifest+json`, and whatever type a framework serves its data payloads as.

A reverse proxy may compress while the origin does not, or the reverse, and the one that answers the request is the one that counts.

And it is invisible in every browser: the page looks identical either way, only slower.

What should not be compressed

Images. JPEG, PNG, WebP and AVIF are already compressed; running gzip over them adds CPU and typically increases the size slightly.

Video and audio, for the same reason.

Archives — anything already a zip, a gzip or a compressed package.

Fonts in WOFF2, which carry Brotli compression internally. WOFF and older formats may still benefit.

So the rule is: compress text, leave binary formats alone. A configuration that compresses everything wastes CPU and occasionally makes responses larger.

How to check it yourself

`curl -I -H 'Accept-Encoding: gzip, br' https://example.com/` and look for a `Content-Encoding` header in the response. Its absence means no compression was applied.

Do it for each resource type, not only the HTML: a CSS file, a JavaScript bundle, a JSON endpoint, an SVG. Compression is configured per MIME type and is frequently right for some and absent for others.

In the Network panel, compare the `Size` and `Content` columns — transferred against uncompressed. Equal values mean the file was sent uncompressed.

Test an uncached URL. A CDN hit may be compressed while the origin response is not, and the origin is what a cold visitor gets.

How to fix it

Enable Brotli with a gzip fallback at whichever layer terminates the connection — the CDN, the reverse proxy, or the web server.

Extend the MIME type list to cover JSON, SVG, web manifests, and any custom type the application serves.

Pre-compress static assets at build time with maximum settings and serve the stored `.br` or `.gz` files. That gets the best compression at no request-time cost.

For dynamic responses, use a moderate compression level. The difference between level 4 and level 11 in Brotli is small in bytes and large in CPU for content compressed on every request.

Confirm afterwards with `curl` on each type rather than on the home page alone.

How VeriFixScan detects it

`performance.compression` reads the `Content-Encoding` of the main document response for each crawled page and reports pages served without compression.

`performance.resource_compression` extends that to the resources the page loads — stylesheets, scripts, data — which is where partial configurations show up.

`performance.page_weight` reports the transferred total, so the saving available is visible as a number rather than as a recommendation.

The check reads what an anonymous client advertising modern encodings receives, which is the same negotiation a real browser performs.

Frequently asked questions

Brotli or gzip?
Brotli where supported, with gzip as the fallback. Brotli produces smaller output; every current major browser supports it over HTTPS, and the negotiation is automatic.
Should images be compressed with gzip?
No. JPEG, PNG, WebP and AVIF are already compressed, and gzip over them costs CPU while typically making the response slightly larger.
Why is my HTML compressed but not my JSON?
Compression is configured per MIME type, and default lists frequently omit application/json, image/svg+xml and application/manifest+json. Extend the list rather than assuming it covers everything.

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