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
no-cacheallows a response to be stored but requires successful validation with the origin before each reuse;no-storetells every cache, private or shared, not to store the response at all. RFC 9111 adds thatno-storeis not a reliable or sufficient mechanism for ensuring privacy, so it is a caching instruction and not a substitute for access control.max-agesets the freshness lifetime for all caches;s-maxageoverrides 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 longmax-age(its example is one year) together withimmutable, which says the response will not be updated while it is fresh.s-maxagealso carries the meaning ofproxy-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 withs-maxagestale, and Google Cloud CDN documents the same, sostale-while-revalidatehas no effect beside it there. Cloudflare’s documented workaround ismax-agewithstale-while-revalidateplus a separate edge TTL rule.privateprevents 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 anAuthorizationheader, and even thenpublic,s-maxage, ormust-revalidatelifts that restriction. A session sent in aCookierequest header triggers no such rule, and RFC 9111 states that aSet-Cookieresponse header does not inhibit caching. Google Cloud CDN declines to cache a response that hasSet-Cookie. Cloudflare, at its default cache level, also declines while Origin Cache Control is enabled, but with it disabled may cache the response with theSet-Cookieheader stripped. Either way that is provider behavior, not a rule of HTTP.- A response without
Cache-Controlcan 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 sinceLast-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 longmax-ageused for successful responses can be stored and replayed by a downstream cache, although which status codes a given CDN stores is provider-specific. Sendno-storeon 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 ignoresno-store,no-cache, andprivateon 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. - 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, orprivate. A Cloudflare Edge Cache TTL rule overridess-maxageand revalidation directives, and Google Cloud CDN’sFORCE_CACHE_ALLmode 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.
Sources
- RFC 9111, Section 5.2: Cache-Control
- RFC 9213: Targeted HTTP Cache Control (CDN-Cache-Control)
- RFC 5861: stale-while-revalidate and stale-if-error
- MDN: Cache-Control header reference
- Cloudflare: Origin Cache Control (directive behavior at the edge)
- Amazon CloudFront: Manage how long content stays in the cache (TTL settings and origin headers)
- Amazon CloudFront: Control how long CloudFront caches errors (Error Caching Minimum TTL)
- Google Cloud CDN: Caching overview (cache modes and directive table)