gzip and Static Performance

Introduction

gzip compresses text responses (HTML, CSS, JS, JSON) before sending them over the network—often cutting transfer size by 60–80%. Nginx can compress on the fly while serving static files. This chapter enables gzip safely, tunes which types compress, and touches other static performance defaults like sendfile.

Prerequisites

Enable gzip

Typically in http block (applies to all sites) or per server:

Code explanation:

  • gzip on — enable compression for eligible responses
  • gzip_vary on — adds Vary: Accept-Encoding for caches
  • gzip_comp_level 5 — balance CPU vs ratio (1 fast, 9 smallest)
  • gzip_min_length 256 — skip tiny files where compression saves little
  • gzip_types — MIME types to compress; text/html compresses by default even if omitted

Reload after edit:

bash
sudo nginx -t && sudo systemctl reload nginx

Verify Compression Works

bash
curl -I -H "Accept-Encoding: gzip" http://127.0.0.1/style.css

Look for:

text
Content-Encoding: gzip

Without the header, response may be uncompressed for that request.

Compare sizes:

bash
curl -s -o /dev/null -w '%{size_download}\n' http://127.0.0.1/app.js
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w '%{size_download}\n' http://127.0.0.1/app.js

Second number should be smaller for text files.

gzip and Precompressed Files

Some builds ship .gz alongside assets. Nginx can serve them with gzip_static:

nginx
location /assets/ {
    gzip_static on;
}

Requires file.css.gz next to file.css. Useful at scale; optional for learning projects.

Brotli (Awareness)

Brotli (br) often beats gzip but needs the ngx_brotli module or newer builds—not always in default distro packages. gzip alone is enough for most VPS setups; CDNs may add Brotli at the edge.

sendfile and TCP Options

Often already set in default nginx.conf:

nginx
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
}

Code explanation:

  • sendfile on — efficient kernel-to-network file transfer for static files
  • tcp_nopush — send headers in one packet when used with sendfile
  • tcp_nodelay — reduce small packet delay for keepalive connections

Rarely change these on first deploy; verify defaults before tuning.

Static Performance Checklist

TechniqueBenefit
gzip / gzip_staticSmaller transfers for text
Long cache on hashed assetsFewer repeat downloads
HTTP/2 (HTTPS chapter)Multiplexing over one connection
Correct MIME typesBrowser parses without fallback delays
worker_processes autoUse available CPU cores

Avoid premature optimization—measure with browser DevTools Network tab and curl.

Combined server Example

For global gzip, move gzip directives to http { } once and drop duplication per site.

When Not to gzip

CaseReason
Already compressed images (PNG, JPEG, WebP)Size may increase
Very small filesOverhead > savings
Streaming / SSECompression may buffer undesirably
CPU-saturated serverLower gzip_comp_level or offload to CDN

Warning

Do Not gzip HTTPS secrets

Compression + TLS on user-specific secrets historically related to BREACH class attacks on dynamic pages—static public assets are fine.

FAQ

gzip in server vs http block?

http — all virtual hosts. server — one site only. Prefer single definition in http.

Does gzip slow the server?

Uses CPU. On small VPS, level 5 is typical. Monitor load under traffic.

Will gzip break old browsers?

Modern clients send Accept-Encoding: gzip. Ancient clients get uncompressed responses.

CDN gzip vs Nginx gzip?

Avoid double compression—either origin or CDN compresses, not both unknowingly.

How does this relate to Vite build?

Vite minifies JS/CSS; Nginx gzip compresses at transfer time—complementary steps.

worker_connections and performance?

Raise in events { } when handling many concurrent clients—advanced tuning; defaults suffice for learning.