Cloudflare Docs
Cache
Edit this page on GitHub
Set theme to dark (⇧+D)

Origin Cache Control

Origin Cache Control is a Cloudflare feature. When enabled on an Enterprise customer’s website, it indicates that Cloudflare should strictly respect Cache-Control directives received from the origin server. Free, Pro and Business customers have this feature enabled by default.

Cache-Control directives in the HTTP response from your origin server provide specific caching instructions to intermediary services like Cloudflare.

With the Origin Cache Control feature enabled, Cache-Control directives present in the origin server’s response will be followed as specified. For example, if the response includes a max-age directive of 3,600 seconds, Cloudflare will cache the resource for that duration before checking the origin server again for updates.

Cloudflare’s Cache Rules allows users to either augment or override an origin server’s Cache-Control headers or default policies set by Cloudflare.

In the following sections, we will provide more details regarding:

  • The most common Cache-Control directives.
  • How to enable Origin Cache Control.
  • How Origin Cache Control behaves with Cache-Control directives.
  • How other Cloudflare products interact with Cache-Control directives.

​​ Cache-control directives

A Cache-Control header can include a number of directives, and the directive dictates who can cache a resource along with how long those resources can be cached before they must be updated.

If multiple directives are passed together, each directive is separated by a comma. If the directive takes an argument, it follows the directive separated by an equal sign. For example: max-age=86400.

Directives can be broken down into four groups: cacheability, expiration, revalidation, and other.

​​ Cacheability

Cacheability refers to whether or not a resource should enter a cache, and the directives below indicate a resource’s cacheability.

  • public — Indicates any cache may store the response, even if the response is normally non-cacheable or cacheable only within a private cache.
  • private — Indicates the response message is intended for a single user, such as a browser cache, and must not be stored by a shared cache like Cloudflare or a corporate proxy.
  • no-store — Indicates any cache, such as a client or proxy cache, must not store any part of either the immediate request or response.

​​ Expiration

Expiration refers to how long a resource should remain in the cache, and the directives below affect how long a resource stays in the cache.

  • max-age=seconds — Indicates the response is stale after its age is greater than the specified number of seconds. Age is defined as the time in seconds since the asset was served from the origin server. The seconds argument is an unquoted integer.
  • s-maxage=seconds — Indicates that in shared caches, the maximum age specified by this directive overrides the maximum age specified by either the max-age directive or the Expires header field. The s-maxage directive also implies the semantics of the proxy-revalidate response directive. Browsers ignore s-maxage.
  • no-cache — Indicates the response cannot be used to satisfy a subsequent request without successful validation on the origin server. This allows an origin server to prevent a cache from using the origin to satisfy a request without contacting it, even by caches that have been configured to send stale responses.

Ensure the HTTP Expires header is set in your origin server to use Greenwich Mean Time (GMT) as stipulated in RFC 2616.

​​ Revalidation

Revalidation determines how the cache should behave when a resource expires, and the directives below affect the revalidation behavior.

  • must-revalidate — Indicates that once the resource is stale, a cache (client or proxy) must not use the response to satisfy subsequent requests without successful validation on the origin server.
  • proxy-revalidate — Has the same meaning as the must-revalidate response directive except that it does not apply to private client caches.
  • stale-while-revalidate=seconds — When present in an HTTP response, indicates caches may serve the response in which it appears after it becomes stale, up to the indicated number of seconds since the resource expired. If Always Online is enabled, then the stale-while-revalidate and stale-if-error directives are ignored. This directive is not supported when using the Cache API methods cache.match or cache.put. For more information, refer to the Worker’s documentation for Cache API.
  • stale-if-error=seconds — Indicates that when an error is encountered, a cached stale response may be used to satisfy the request, regardless of other freshness information. To avoid this behavior, include stale-if-error=0 directive with the object returned from the origin. This directive is not supported when using the Cache API methods cache.match or cache.put. For more information, refer to the Worker’s documentation for Cache API.

The stale-if-error directive is ignored if Always Online is enabled or if an explicit in-protocol directive is passed. Examples of explicit in-protocol directives include a no-store or no-cache cache directive, a must-revalidate cache-response-directive, or an applicable s-maxage or proxy-revalidate cache-response-directive.

​​ Other

Additional directives that influence cache behavior are listed below.

  • no-transform — Indicates that an intermediary — regardless of whether it implements a cache — must not transform the payload.
  • vary — Cloudflare does not consider vary values in caching decisions. Nevertheless, vary values are respected when Vary for images is configured and when the vary header is vary: accept-encoding.
  • immutable — Indicates to clients the response body does not change over time. The resource, if unexpired, is unchanged on the server. The user should not send a conditional revalidation request, such as If-None-Match or If-Modified-Since, to check for updates, even when the user explicitly refreshes the page. This directive has no effect on public caches like Cloudflare, but does change browser behavior.

​​ Enable Origin Cache Control

If you enable Origin Cache Control, Cloudflare will aim to strictly adhere to RFC 7234. Enterprise customers have the ability to select if Cloudflare will adhere to this behavior, enabling or disabling Origin Cache Control for their websites through cache rules in the dashboard or via API. Free, Pro, and Business customers have this option enabled by default and cannot disable it.

​​ Origin Cache Control behavior

The following section covers the directives and behavioral conditions associated with enabling or disabling Origin Cache Control.

​​ Directives

The table below lists directives and their behaviors when Origin Cache Control is disabled and when it is enabled.

DirectiveOrigin Cache Control disabled behaviorOrigin Cache Control enabled behavior
s-maxage=0Will not cache.Caches and always revalidates
max-age=0Will not cache.Caches and always revalidates.
no-cacheWill not cache.Caches and always revalidates. Does not serve stale.
no-cache=<headers>Will not cache.Caches if headers mentioned in no-cache=<headers> do not exist. Always revalidates if any header mentioned in no-cache=<headers> is present.
Private=<headers>Will not cache.Does not cache <headers> values mentioned in Private=<headers> directive.
must-revalidateCache directive is ignored and stale is served.Does not serve stale. Must revalidate for CDN but not for browser.
proxy-revalidateCache directive is ignored and stale is served.Does not serve stale. Must revalidate for CDN but not for browser.
no-transformMay (un)Gzip, Polish, email filter, etc.Does not transform body.
s-maxage=delta, delta>1Same as max-age.Max-age and proxy-revalidate.
immutableNot proxied downstream.Proxied downstream. Browser facing, does not impact caching proxies.

​​ Conditions

Certain scenarios also affect Origin Cache Control behavior when it is enabled or disabled.

ConditionOrigin Cache Control disabled behaviorOrigin Cache Control enabled behavior
Presence of Authorization header.Content may be cached.Content is cached only if must-revalidate, public, or s-maxage is also present.
Use of no-cache header.In logs, cacheStatus=miss.In logs, cacheStatus=bypass.
Origin response has Set-Cookie header and default cache level is used.Content may be cached with stripped set-cookie header.Content is not cached.
Browser Cache TTL is set.`Cache-Control` returned to eyeball does not include private.If origin returns private in `Cache-Control` then preserve it.

​​ Examples

Review the examples below to learn which directives to use with the Cache-Control header to control specific caching behavior.

Cache a static asset.
Cache-Control: public, max-age=86400
Ensure a secret asset is never cache.
Cache-Control: no-store
Cache assets on browsers but not on proxy cache.
Cache-Control: private, max-age=3600
Cache assets in client and proxy caches, but prefer revalidation when serve.
Cache-Control: public, no-cache
Cache assets in proxy caches but REQUIRE revalidation by the proxy when serve.
Cache-Control: public, no-cache, proxy-revalidate or Cache-Control: public, s-maxage=0
Cache assets in proxy caches, but REQUIRE revalidation by any cache when serve.
Cache-Control: public, no-cache, must-revalidate
Cache assets, but ensure the proxy does not modify it.

Cache-Control: public, no-transform

This configuration also disables transformation like gzip or brotli compression from our edge to your visitors if the original payload was served uncompressed.

Cache assets with revalidation, but allow stale responses if origin server is unreachable.

Cache-Control: public, max-age=3600, stale-if-error=60

With this configuration, Cloudflare attempts to revalidate the content with the origin server after it has been in cache for 3600 seconds (one hour). If the server returns an error instead of proper revalidation responses, Cloudflare continues serving the stale resource for a total of one minute beyond the expiration of the resource.

Cache assets for different amounts of time on Cloudflare and in visitor browsers.
Cache-Control: public, max-age=7200, s-maxage=3600
Cache an asset and serve while asset is being revalidated.

Cache-Control: max-age=600, stale-while-revalidate=30

This configuration indicates the asset is fresh for 600 seconds. The asset can be served stale for up to an additional 30 seconds to parallel requests for the same resource while the initial synchronous revalidation is attempted.

​​ Interaction with other Cloudflare features

In this section, we provide details regarding how other Cloudflare features interact with Cache-Control directives.

​​ Edge Cache TTL

Edge Cache TTL Cache Rules override s-maxage and disable revalidation directives if present. When Origin Cache Control is enabled at Cloudflare, the original Cache-Control header passes downstream from our edge even if Edge Cache TTL overrides are present. Otherwise, when Origin Cache Control is disabled at Cloudflare, Cloudflare overrides the Origin Cache Control.

​​ Browser Cache TTL

Browser Cache TTL Page Rules override max-age settings passed downstream from our edge, typically to your visitor’s browsers.

​​ Polish

Polish is disabled when the no-transform directive is present.

​​ Gzip and Other Compression

Compression is disabled when the no-transform directive is present. If the original asset fetched from the origin is compressed, it is served compressed to the visitor. If the original asset is uncompressed, compression is not applied.