What Gzip Compression Does
Gzip compression reduces the number of bytes Nginx sends over the wire by finding and encoding repeated patterns in a response body, which works especially well on text-heavy formats like HTML, CSS, JavaScript, and JSON where the same tags, keywords, and whitespace repeat constantly. A typical HTML or JSON response can shrink by 60-80% after gzip, meaning faster page loads for users on slower connections and lower bandwidth costs for the server, at the expense of some CPU time spent compressing on the way out.
Cricket analogy: Compressing a webpage's HTML before sending it over the wire is like a broadcaster sending condensed match highlights instead of the full six-hour Test day feed — gzip strips redundant patterns so viewers (browsers) get the same information using far less bandwidth.
Configuring gzip Directives
Turning gzip on; alone does very little because Nginx only compresses text/html by default; the gzip_types directive must explicitly list every MIME type you actually want compressed, such as application/json or text/css. gzip_comp_level trades compression ratio against CPU cost on a 1-9 scale, while gzip_min_length skips compressing responses too small for the overhead to be worthwhile, and gzip_proxied controls whether proxied responses (from an upstream) are eligible for compression at all.
Cricket analogy: gzip_min_length 1000; is like a team management deciding it's only worth reviewing DRS footage for close decisions, not every routine dot ball — Nginx skips compressing tiny responses where the overhead isn't worth the savings.
http {
gzip on;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
gzip_proxied any;
gzip_disable "msie6";
}gzip_vary and Shared Caches
Setting gzip_vary on; adds a Vary: Accept-Encoding response header, telling any downstream cache or CDN that the compressed and uncompressed versions of a response are distinct and must be stored separately. Without it, a shared cache sitting between Nginx and the client could serve a gzip-compressed response to a client that never sent an Accept-Encoding: gzip header, resulting in garbled, unreadable output for that user.
Cricket analogy: Setting gzip_vary on; adds a Vary: Accept-Encoding header, similar to a stadium scoreboard operator noting which broadcast feed format (HD vs SD) was requested so a relay station downstream doesn't accidentally rebroadcast the wrong version to a different audience.
Always pair gzip_vary on; with any gzip configuration behind a shared cache or CDN — without it, an intermediary may serve a compressed response to a client that sent no Accept-Encoding header, causing garbled output.
Brotli and Compression Alternatives
Brotli, a newer compression algorithm developed by Google, typically compresses text-based responses 15-20% smaller than gzip at comparable settings, making it attractive for static CSS and JavaScript bundles served at scale. It requires the third-party ngx_brotli module rather than being built into stock Nginx, and it shines most when assets are precompressed once at build/deploy time rather than compressed fresh on every single request, since Brotli's higher compression levels are noticeably more CPU-intensive than gzip's.
Cricket analogy: Brotli generally compresses text 15-20% smaller than gzip at equivalent settings, much like a more disciplined bowling attack that concedes noticeably fewer runs per over than an average attack for the same number of deliveries bowled.
Brotli support requires the third-party ngx_brotli module, which is not compiled into stock Nginx — you must build Nginx from source with --add-module or use a distribution that bundles it, such as nginx.org's dynamic module packages.
- gzip on; alone does nothing without gzip_types listing the MIME types you want compressed.
- gzip_comp_level trades CPU cost for compression ratio; level 6 is a reasonable default for most workloads.
- gzip_min_length avoids wasting CPU compressing responses too small to benefit.
- gzip_vary on; adds the Vary: Accept-Encoding header, essential for correctness behind shared caches and CDNs.
- Already-compressed formats like JPEG, PNG, and video should not be gzipped — there's no benefit and it wastes CPU.
- Brotli via the ngx_brotli module typically compresses text 15-20% smaller than gzip but requires a custom Nginx build.
- Precompressing static assets at build time avoids paying the compression CPU cost on every request.
Practice what you learned
1. What must be true for gzip to actually compress a response, even with gzip on;?
2. What does gzip_vary on; add to responses, and why does it matter?
3. Why is it generally wasteful to apply gzip to JPEG or already-compressed video files?
4. What is the main practical difference between Brotli and gzip compression in Nginx?
5. What does gzip_comp_level control?
Was this page helpful?
You May Also Like
Nginx Caching Explained
How Nginx's proxy_cache module stores upstream responses to cut backend load and speed up delivery, and how to configure, key, and invalidate that cache correctly.
Connection and Buffer Tuning
How worker, connection, and buffer settings determine Nginx's throughput ceiling, and how to tune them safely for high-concurrency workloads.
Nginx Performance Benchmarking
How to rigorously measure Nginx throughput and latency with tools like ab and wrk, interpret latency percentiles, and avoid common benchmarking pitfalls.
Related Reading
Related Study Notes in DevOps
Browse all study notesAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics