What is the Cache-Control Header?

Cache-Control is an HTTP request or response header whose directives govern storage, freshness, revalidation, and reuse by caches. Different directives can apply to browsers and shared intermediaries.

How the Cache-Control Header works

Cache-Control communicates policy through comma-separated directives attached to an HTTP request or response. Freshness directives determine when reuse can occur without contacting the origin, while storage, validation, and scope directives constrain what private and shared caches may retain or serve. Response directives are binding on a conforming cache, whereas request directives are advisory, and a CDN may ignore the ones that would let a client force a trip to the origin: Google Cloud CDN, for example, ignores no-cache and max-age in requests. The header speaks to every cache on the path at once and cannot address a specific one, which is why RFC 9213 defines CDN-Cache-Control, a separate response header with the same directives that a supporting CDN cache uses in place of Cache-Control.

Key facts

  1. no-cache allows a response to be stored but requires successful validation with the origin before each reuse; no-store tells every cache, private or shared, not to store the response at all. RFC 9111 adds that no-store is not a reliable or sufficient mechanism for ensuring privacy, so it is a caching instruction and not a substitute for access control.
  2. max-age sets the freshness lifetime for all caches; s-maxage overrides it in shared caches such as CDNs and is ignored by browsers. For a file whose URL changes whenever its content does, MDN’s pattern is a long max-age (its example is one year) together with immutable, which says the response will not be updated while it is fresh. s-maxage also carries the meaning of proxy-revalidate: once the response is stale, a shared cache must revalidate it before reuse. With Origin Cache Control enabled, which is the default on its Free, Pro, and Business plans, Cloudflare does not serve a response with s-maxage stale, and Google Cloud CDN documents the same, so stale-while-revalidate has no effect beside it there. Cloudflare’s documented workaround is max-age with stale-while-revalidate plus a separate edge TTL rule.
  3. private prevents storage by shared caches but permits the browser’s own cache, so it is different from disabling caching. It has to be set deliberately on personalized responses. HTTP withholds a response from shared caches on its own only when the request carried an Authorization header, and even then public, s-maxage, or must-revalidate lifts that restriction. A session sent in a Cookie request header triggers no such rule, and RFC 9111 states that a Set-Cookie response header does not inhibit caching. Google Cloud CDN declines to cache a response that has Set-Cookie. Cloudflare, at its default cache level, also declines while Origin Cache Control is enabled, but with it disabled may cache the response with the Set-Cookie header stripped. Either way that is provider behavior, not a rule of HTTP.
  4. A response without Cache-Control can still be cached. RFC 9111 lets a cache assign a heuristic lifetime to a heuristically cacheable response that has no explicit expiration, suggesting no more than a fraction of the time since Last-Modified, and CDNs apply their own default lifetime when the origin sends none. Errors are covered by the same rules: a final response with explicit freshness may be stored, so a 5xx sent with the long max-age used for successful responses can be stored and replayed by a downstream cache, although which status codes a given CDN stores is provider-specific. Send no-store on anything that must not be cached, and do not attach success-path lifetimes to error responses. A CDN can also cache errors under a setting of its own that the header does not switch off: Amazon CloudFront ignores no-store, no-cache, and private on 500, 502, 503, and 504 responses and caches them for its Error Caching Minimum TTL, which is set per status code and defaults to 10 seconds. It does not cache these errors when the cache behavior uses the CachingDisabled managed cache policy.
  5. The origin’s header is not always the last word at the edge. Amazon CloudFront uses the cache policy’s minimum TTL when it is greater than 0, even if the origin sent no-cache, no-store, or private. A Cloudflare Edge Cache TTL rule overrides s-maxage and revalidation directives, and Google Cloud CDN’s FORCE_CACHE_ALL mode caches successful responses regardless of origin directives. Check the CDN’s TTL and override settings before relying on a directive to keep a response out of a shared cache.

When the Cache-Control Header matters

Set Cache-Control according to whether a response is public, private, immutable, or frequently updated. Conflicting or overly permissive directives can expose private data or preserve stale media.

How Transloadit helps with the Cache-Control Header

When Transloadit serves a transformed file through Smart CDN, the /file/serve Robot sets the Cache-Control header of the result, with a browser lifetime in max-age and a separate shared-cache lifetime in s-maxage. The Robot’s cache_duration parameter sets both directives to one value, and its headers parameter merges your own header values over the defaults. For signed Smart CDN URLs, the effective cache lifetime is additionally bounded by the remaining signature lifetime.

The Robot page lists the current default lifetimes.

Explore Transloadit’s delivery capabilities

Sources

Turn media knowledge into a working pipeline

Connect uploads, processing, AI, storage, and delivery through one declarative API — with the encoding stack, scaling, and format churn handled for you.

Try Transloadit for free