How to Build a Cache-Control Header (max-age, immutable, no-store)

How to Build a Cache-Control Header (max-age, immutable, no-store)

The Cache-Control header tells browsers and CDNs how long to keep a response and whether they can reuse it. Get it right and your site loads from cache instead of the network. Get it wrong and you either serve stale pages or force needless downloads. Here is what each directive does and how to build the header for your case.

What the Cache-Control directives mean

  • max-age=N: how long, in seconds, a response is fresh. max-age=31536000 is one year.
  • s-maxage=N: same idea, but for shared caches like a CDN. It overrides max-age there.
  • public: any cache may store the response, including a CDN.
  • private: only the user’s browser may store it, never a shared cache. Use this for per-user content.
  • no-cache: the response may be stored, but it must be revalidated with the server before reuse.
  • no-store: never store the response at all. Use it for sensitive data.
  • must-revalidate: once stale, the cache must check with the server rather than serve the old copy.
  • immutable: tells the browser the file will never change, so it skips revalidation entirely.

Pick the right header per asset

A few patterns cover most cases:

  • Hashed or fingerprinted static assets (like app.4f3a.js): use public, max-age=31536000, immutable. The filename changes when the content changes, so you can cache for a year and skip revalidation.
  • HTML pages: use no-cache or a short max-age. The URL stays the same while the content changes, so you want a fresh check each time.
  • Sensitive or per-user responses (account pages, API tokens): use no-store so nothing is written to disk.
  • Images and fonts you may update: a moderate max-age plus must-revalidate keeps them cached but checkable.

For revalidation, pair caching with an ETag or Last-Modified header. The browser sends the saved value back, and the server replies 304 Not Modified when nothing changed, saving the full download.

Build your header in three steps

  1. Open the Cache-Control Header Generator and choose your audience with public or private.
  2. Set max-age (and s-maxage if you use a CDN), then toggle immutable, no-store, no-cache, or must-revalidate as your asset needs.
  3. Copy the generated value and drop it into your server config or framework response.

The Cache-Control Header Generator explains each option in plain language as you toggle it, and it runs entirely in your browser, so nothing you enter is sent anywhere.

Cache hashed assets for a year with immutable, keep HTML on no-cache, and no-store anything sensitive. Build it, copy it, ship it.

← All posts