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?