caching

Cache-Control

Directs caching behavior in both requests and responses per RFC 9111, controlling freshness, revalidation, and where the response may be stored. Directives can be combined and are respected by browsers, CDNs, and intermediate proxies.

Cache-Control: <directive>[, <directive>...]  (e.g. max-age=3600, s-maxage=86400, public, no-cache, no-store, private, must-revalidate, immutable, stale-while-revalidate=<seconds>)

Common directives / values

Directive Purpose
max-age=<seconds> Response is fresh for this many seconds in any cache.
s-maxage=<seconds> Overrides max-age for shared caches (CDN/proxy) only.
public Explicitly allows any cache to store the response, even if normally not cacheable.
private Only the end-user's browser may cache; forbids shared caches like CDNs.
no-cache Cache may store but must revalidate with the origin before reuse.
no-store Do not store the response in any cache anywhere.
must-revalidate Once stale, must revalidate; do not serve stale on errors.
immutable Response body will not change during its freshness lifetime; suppresses reload revalidations.

Examples

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

Ideal for fingerprinted static assets (e.g. app.abc123.js) served by a CDN.

Cache-Control: private, no-cache

Personalized HTML: browser may store but must revalidate with ETag each visit.

Cache-Control: no-store

Sensitive banking/auth responses that must never touch disk or intermediary caches.

Cache-Control: public, max-age=60, s-maxage=600, stale-while-revalidate=86400

Browser caches 1min, CDN 10min, may serve stale for 24h while re-fetching in background.

Gotcha

Cache-Control: private prevents CDN caching but still allows the browser to cache. no-cache does NOT mean 'do not cache' — that is no-store; no-cache means 'store but revalidate before use'.

Related headers

← All HTTP headers · HTTP status codes · Fix CORS errors