| [ Web Proxy ] |
| Viewing: https://developers.cloudflare.com/cache/concepts/cache-control/#conditions | [Back] [Original] |
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.
The following sections cover:
Cache-Control directives.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.
Note
For more information about Cache-Control directives at origin servers, refer to the Mozilla Cache-Control documentation .
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 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 refers to how long a resource should remain in the cache, and the directives below affect how long a resource stays in the cache.
Note
Cloudflare respects whichever value is higher: the Browser Cache TTL in Cloudflare or the max-age header. You can also simultaneously specify a Cloudflare Edge Cache TTL different than a Browser's Cache TTL respectively via the s-maxage and max-age Cache-Control headers.
When using Origin Cache Control and setting max-age=0, Cloudflare prefers to cache and revalidate. With Origin Cache Control off and max-age=0, Cloudflare will bypass cache.
When setting no-cache with Origin Cache Control off, Cloudflare does not cache. When setting no-cache with Origin Cache Control on, Cloudflare caches and always revalidates.
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.`s-maxage` disables `stale-while-revalidate`
Per RFC 9111 , s-maxage incorporates the semantics of proxy-revalidate, which means a shared cache must not serve stale content without first revalidating with the origin. For a complete list of directives that disable stale-while-revalidate and workarounds, refer to Controlling stale behavior.
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 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 Workers documentation for Cache API.Note
stale-while-revalidate is now fully asynchronous. The first request after expiry triggers revalidation in the background and immediately receives stale content with an UPDATING status instead of blocking. All requests during revalidation are served stale with an UPDATING status until the origin responds, after which they receive a HIT.
For more details, refer to Revalidation.
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 Workers documentation for Cache API.Error status codes
The stale-if-error directive triggers when your origin returns a 5xx status code (500, 502, 503, 504). Other responses such as 404 are not considered errors for this purpose the origin response replaces the stale cached content. There is currently no way to customize which status codes trigger stale-if-error.
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.
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 By default, Cloudflare does not consider vary values in caching decisions. Vary values are respected when you configure the Cache Rules Vary setting, 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.There is often confusion between the directives Cache-Control: no-store and Cache-Control: no-cache, particularly regarding how they impact browser caching and features like the Back-Forward Cache (BFCache).
no-store disables BFCache, because restoring a page from BFCache requires the browser to keep a copy of the page's memory state, which contradicts the do not store directive.For more information about how these directives behave when Origin Cache Control is enabled or disabled refer to the Directives section.
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.
The following section covers the directives and behavioral conditions associated with enabling or disabling Origin Cache Control.
Integer values required
The max-age, s-maxage, and stale-while-revalidate directives require integer values per RFC 9111. Floating-point values (for example, max-age=2.5) are not valid and will be ignored, potentially causing cache bypass. Ensure your origin returns integer TTL values.
The table below lists directives and their behaviors when Origin Cache Control is disabled and when it is enabled.
| Directive | Origin Cache Control Disabled Behavior | Origin Cache Control Enabled Behavior |
|---|---|---|
s-maxage=0 |
Will not cache. | Caches and always revalidates |
max-age=0 |
Will not cache. | Caches and always revalidates. |
no-cache |
Will 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-revalidate |
Cache directive is ignored and stale is served. | Does not serve stale. Must revalidate for CDN and for browser. |
proxy-revalidate |
Cache directive is ignored and stale is served. | Does not serve stale. Must revalidate for CDN but not for browser. |
no-transform |
May (un)Gzip, Polish, email filter, etc. | Does not transform body. |
s-maxage=delta, delta>1 |
Same as max-age. |
Max-age and proxy-revalidate. |
immutable |
Not proxied downstream. | Proxied downstream. Browser facing, does not impact caching proxies. |
no-store |
Will not cache. | Will not cache. |
Certain scenarios also affect Origin Cache Control behavior when it is enabled or disabled.
Condition | Origin Cache Control disabled behavior | Origin Cache Control enabled behavior | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Presence of | Content may be cached. | Content is cached only if | ||||||||||||
Use of | In logs, | In logs, | ||||||||||||
Origin response has | Content may be cached with stripped | Content is not cached. | ||||||||||||
Browser Cache TTL is set. |
| If origin returns |
Note
When the Cloudflare-Cdn-Cache-Control header is set, OCC is turned on (regardless of whether OCC is enabled or disabled). As a result, we apply our Authorization header logic (per RFC 7234, Section 3.2 ) to allow only the s-maxage, must-revalidate, or public directives. If any other directive is present, we do not cache the asset and instead return BYPASS.
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 cached.
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 while Cloudflare revalidates the asset with the origin in the background. For more information, refer to Revalidation.
Note
Do not use s-maxage with stale-while-revalidate. The s-maxage directive implies proxy-revalidate, which prevents shared caches from serving stale content. For workarounds, refer to Controlling stale behavior.
This section covers how other Cloudflare features interact with Cache-Control directives.
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 Cache Rules override max-age settings passed downstream from our edge, typically to your visitor's browsers.
Polish is disabled when the no-transform directive is present.
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.
JavaScript Detections injection is disabled when the no-transform directive is present. The cf.bot_management.js_detection.passed field will show as missing for affected requests.
| Web Proxy Viewer | New URL | Original Page |