Website Spec
← Performance
Required

Cache-Control headers

Cache-Control tells browsers and CDNs how long to keep a response. Use immutable + max-age=31536000 for fingerprinted assets and short or no-cache for HTML.

What it is

Cache-Control is an HTTP response header that governs how, where, and for how long a response may be stored and reused. It is defined in RFC 9111 and replaces the older Expires and Pragma headers.

Cache-Control: public, max-age=31536000, immutable

Key directives:

Why it matters

A correct cache policy is the cheapest possible performance win. Repeat visitors download nothing for cached assets. CDNs absorb traffic before it reaches your origin. Without it, every page view re-fetches the same CSS, JS, and images. With it, the second visit can be near-instant.

no-cache is also a privacy tool: it forces revalidation of HTML so users see your latest content, while still allowing 304s.

How to implement

Fingerprinted assets — cache forever. If the URL contains a content hash (app.4f3a2b.js), the body cannot change. Cache aggressively:

Cache-Control: public, max-age=31536000, immutable

immutable matters: without it, Firefox revalidates on reload even with max-age set.

HTML — short or no cache. Pages change often and rarely have fingerprinted URLs. Use:

Cache-Control: public, max-age=0, must-revalidate

or, for highly dynamic pages:

Cache-Control: no-store

Pair with ETag so revalidation is cheap.

Per-user content — private. Anything personalised needs private to prevent shared caches from leaking one user's data to another.

Set Vary correctly. If the response varies by Accept-Encoding or Accept-Language, set Vary accordingly. Missing Vary causes a CDN to serve gzip to a client that asked for brotli.

Common mistakes

Verification

Sources