HTTP Caching (Cache-Control)

How the Cache-Control header controls whether and how long a response can be reused without asking the server again.

                Cache-Control: max-age=3600 / no-cache / no-store
              

Purpose

The Cache-Control response header tells the browser (and any intermediate cache) whether and for how long a response may be reused without contacting the server again.

Common directives

Cache-Control: max-age=3600, must-revalidate
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: private
  • max-age=<seconds>: how long the response is considered fresh, no revalidation needed.
  • no-cache: store it, but revalidate with the server before every reuse — despite the name, this does not disable caching.
  • no-store: never store this response at all — the directive that actually disables caching.
  • private: only a browser’s own cache may store this (not a shared intermediate cache, such as a CDN) — appropriate for user-specific responses.
  • must-revalidate: once stale (past max-age), the cache must revalidate rather than serving a stale copy if the server is unreachable.

Behavior notes

  • Fingerprinted, immutable assets (a filename containing a content hash) can safely use a very long max-age — the filename itself changes whenever the content does, so staleness is a non-issue.
  • HTML and other frequently-changing responses typically use a short max-age or no-cache, to balance freshness against unnecessary re-fetches.
  • ETag/Last-Modified headers pair with no-cache/revalidation: the browser sends the cached value’s identifier, and the server responds with a cheap 304 Not Modified if nothing changed, avoiding re-sending the full body.

Common mistakes

  • Assuming no-cache means “don’t cache” — it means “cache, but always check first.”
  • Setting a long max-age on a resource whose URL doesn’t change when its content does, causing stale content to persist for clients until the cache duration expires.

Runtime notes

Part of the HTTP standard, honored by browsers, CDNs, and any HTTP-caching-aware client — not JavaScript-specific, though fetch’s cache option lets a script influence its own request’s caching behavior.

Taught in these lessons

Related reference

Updated 2026-09-03