The nginx caching and compression layer
Updated Jun 29, 2026 · 2 min read
Understand the gzip compression and cache-control headers configured in nginx-ha/nginx.conf, and how to safely change them.
Gzip compression
The nginx config at nginx-ha/nginx.conf enables gzip compression for text-based responses. The relevant directives are:
- gzip on — turns compression on
- gzip_vary on — adds a "Vary: Accept-Encoding" header so caches store compressed and uncompressed copies separately
- gzip_comp_level 6 — a balanced compression level (CPU cost vs ratio)
- gzip_min_length 1024 — only compress responses larger than 1 KB (compressing tiny responses wastes CPU)
- gzip_types — the list of MIME types to compress, including text/css, application/javascript, application/json, image/svg+xml, and font/woff2
Caching Next.js static assets
A "location /_next/static/" block adds the header:
Cache-Control: public, max-age=31536000, immutable
This tells browsers (and any proxy in front, including Cloudflare) that these files can be cached for a year and are immutable — the browser will not even revalidate them. This is safe because Next.js content-hashes every filename in /_next/static/.
Caching other static file types
A regex location block "location ~* \.(js|css|woff2|...)$" adds the header:
Cache-Control: public, max-age=2592000
That is 30 days. This covers static assets that live outside /_next/static/ and are not content-hashed, so a 30-day TTL is used instead of the immutable one-year policy.
Dynamic and HTML routes are deliberately not cached
There is no caching applied to dynamic pages or HTML responses. This is intentional: every HTML page is rendered per-user behind Clerk authentication. Caching an HTML route could leak one user's authenticated page to another. Only static assets (JS, CSS, fonts, images) are cached — never the per-request HTML.
Validating and reloading after a config change
After editing nginx.conf, always validate the syntax before reloading:
nginx -t
If it reports "syntax is ok" and "test is successful", reload nginx to apply the change (nginx -s reload, or restart the nginx container). Remember that nginx matches regex location blocks (the ~* ones) before the prefix "location /" block, so the static-asset rules take precedence over the catch-all even though the catch-all appears to match everything.
Was this helpful?