Brotli vs gzip Compression
debt(d7/e2/b3/t5)
Closest to 'only careful code review or runtime testing' (d7), detection_hints list curl/lighthouse/chrome-devtools and automated:no — you have to inspect response headers manually or run a perf audit; no linter flags ob_gzhandler.
Closest to 'one-line patch or single-call swap' (e1, scored e2), quick_fix is to remove ob_gzhandler/zlib.output_compression and configure nginx — mostly a config swap, slightly more than one line because nginx config also needs adjusting.
Closest to 'localised tax' (b3), applies to web context only and affects the response pipeline of one component; doesn't reshape the codebase but does impose ongoing CPU cost per request until fixed.
Closest to 'notable trap (documented gotcha)' (t5), misconception that ob_gzhandler equals server-level compression is a well-known but easy-to-miss issue — developers reasonably assume PHP-level compression is fine, missing that nginx caches compressed output.
Also Known As
TL;DR
Explanation
HTTP response compression reduces transfer size by 60-80% for text content (HTML, CSS, JS, JSON). gzip: universal support, good compression. Brotli: designed for web, 15-25% better compression than gzip, slightly slower to compress (pre-compress static files), supported by all modern browsers via Accept-Encoding: br. Configure at nginx/Apache level — never use PHP's ob_gzhandler() in production as it adds CPU overhead on every request without the benefits of server-level caching. Pre-compress static assets at build time.
Common Misconception
Why It Matters
Common Mistakes
- ob_gzhandler() in production PHP — use nginx/Apache compression instead.
- Not pre-compressing static assets — serve pre-built .br and .gz files directly.
- Compressing already-compressed content (images, videos) — wastes CPU with no benefit.
- No Vary: Accept-Encoding header — CDNs may serve compressed content to clients that don't support it.
Code Examples
// PHP-level compression — runs on every request:
// php.ini:
zlib.output_compression = On
// or:
ob_start('ob_gzhandler');
// CPU overhead per request, no caching, misses static file benefits
# nginx — server-level Brotli + gzip:
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json;
gzip on;
gzip_comp_level 5;
gzip_types text/plain text/css application/javascript application/json;
gzip_vary on; # Add Vary: Accept-Encoding
# Pre-compressed static assets:
location ~* \.(js|css|html)$ {
gzip_static on; # Serve .gz if exists
brotli_static on; # Serve .br if exists
}