Configuration: HTTP compression
This page documents the Ferron HTTP compression system. It covers the algorithm preference order, supported algorithms, and configuration options.
The http-compression module handles compression. For static file compression specifically, see Static file serving.
Algorithm preference#
When a client sends an Accept-Encoding header, Ferron selects the best compression algorithm based on a preference order:
- Zstandard: the preferred algorithm. Offers the best compression ratio for text content and fast decoding.
- Brotli: excellent compression ratio, widely supported.
- gzip: the most universally supported compression algorithm.
- Deflate: similar to gzip but without the CRC checksum overhead. Less common in practice.
The server iterates through the Accept-Encoding header values that the client sends. It selects the first algorithm that matches the preference order. For example, if a client sends:
Accept-Encoding: gzip, br, zstdThe server selects Zstandard because it appears first in the preference order, even though the client listed gzip first.
If the client does not send an Accept-Encoding header, the server serves the response without compression (identity). The same applies when none of the supported algorithms appear in the header.
Configuration#
Ferron uses two separate directives for the two response paths. Do not mix them up.
Static file compression#
The compressed directive (http-static) enables on-the-fly compression for static file responses only. It applies when Ferron serves files from root. Ferron compresses files larger than 256 bytes with compressible extensions. Default: compressed true
Dynamic response compression#
The dynamic_compressed directive (http-compression) enables on-the-fly compression for dynamic response bodies, such as reverse proxy, FastCGI, and CGI responses. It does not affect static files. Use it when backends return compressible text without their own compression. Default: dynamic_compressed false
Ferron never compresses 101 Switching Protocols responses. Protocol upgrades such as WebSockets pass through unchanged when dynamic_compressed is on.
Pre-compressed sidecar files#
precompressed [bool: boolean](http-static)- Enables serving pre-compressed sidecar files (for example,
style.css.zst,app.js.br) instead of compressing on the fly. The server checks for a pre-compressed file alongside the original based on which algorithms the client lists inAccept-Encoding. Default:precompressed false
- Enables serving pre-compressed sidecar files (for example,
Configuration example:
example.com {
root /srv/www/example
compressed
dynamic_compressed
precompressed
}Algorithm details#
| Algorithm | Content-Encoding value | Pre-compressed file extension | ETag suffix | Encoding parameters |
|---|---|---|---|---|
| Zstandard | zstd | .zst | -zstd (static files), -dynamic-zstd (dynamic responses) | Quality level 4, window log 17, hash log 10 |
| Brotli | br | .br | -br (static files), -dynamic-br (dynamic responses) | Quality level 4, window size 17, block size 18 |
| gzip | gzip | .gz | -gzip (static files), -dynamic-gzip (dynamic responses) | Quality level 4 |
| Deflate | deflate | .deflate | -deflate (static files), -dynamic-deflate (dynamic responses) | Quality level 4 |
Browser compatibility#
Ferron detects and handles browsers with known compression bugs:
- Netscape 4.x (non-IE): Ferron disables compression for text/html content.
- w3m/0.5.x: Ferron disables HTML compression.
- IE masquerading as Netscape 4.x: Ferron allows compression (
MSIEin the user agent indicates it is safe).
ETag handling#
When Ferron applies compression, it modifies the ETag to distinguish compressed variants:
- Static files: Ferron appends a suffix to the ETag (for example,
W/"abc123-zstd"for zstd-compressed files). Pre-compressed sidecar files receive their own ETag. That ETag derives from the metadata of the sidecar file. - Dynamic responses: Ferron appends a
-dynamic-prefixed suffix (for example,W/"abc123-dynamic-zstd").
When the If-None-Match header is present, the server checks both the base ETag and the compressed variant. This determines whether to return 304 Not Modified.
Vary header#
When compression is possible (based on file size and extension), the server adds Accept-Encoding to the Vary header. This makes sure caches serve the correct compressed variant to each client.
Observability#
Access log fields#
The compression module contributes the following field to the HTTP access log line:
| Field | Type | Description |
|---|---|---|
ferron.compression.algorithm | string | Compression algorithm: gzip, br, deflate, zstd, or identity. |
Trace spans#
The dynamic compression stage sets the following attributes on its ferron.stage.dynamic_compression span:
| Attribute | Type | Description |
|---|---|---|
ferron.compression.algorithm | string | Compression algorithm used: gzip, br, deflate, zstd, or identity. |
ferron.compression.precompressed | bool | Whether the server served a precompressed file variant. |