diff --git a/src/content/docs/cache/concepts/cache-control.mdx b/src/content/docs/cache/concepts/cache-control.mdx index d2204b47500e6b4..1144f7196b7a327 100644 --- a/src/content/docs/cache/concepts/cache-control.mdx +++ b/src/content/docs/cache/concepts/cache-control.mdx @@ -69,7 +69,13 @@ When setting `no-cache` with Origin Cache Control off, Cloudflare does not 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`. +* `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`. + +:::caution[`s-maxage` disables `stale-while-revalidate`] +Per [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-4), `s-maxage` incorporates the semantics of `proxy-revalidate`, which means a shared cache must not serve stale content without first revalidating with the origin. When `s-maxage` is present, Cloudflare will not honor `stale-while-revalidate` — the cache will return `EXPIRED` instead of serving stale content with an `UPDATING` status. + +If you need different TTLs for browsers and Cloudflare while still using `stale-while-revalidate`, use `max-age` with `stale-while-revalidate` at the origin and set a separate [Edge Cache TTL](/cache/how-to/cache-rules/settings/#edge-ttl) via Cache Rules. +::: * `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](https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 "3.3.1 Full Date"). @@ -298,6 +304,10 @@ With this configuration, Cloudflare attempts to revalidate the content with the 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](/cache/concepts/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. If you need a different TTL for Cloudflare than for browsers, use [Edge Cache TTL](/cache/how-to/cache-rules/settings/#edge-ttl) in Cache Rules instead. +::: + diff --git a/src/content/docs/cache/concepts/revalidation.mdx b/src/content/docs/cache/concepts/revalidation.mdx index be6792de1f48057..75c9633cf918c53 100644 --- a/src/content/docs/cache/concepts/revalidation.mdx +++ b/src/content/docs/cache/concepts/revalidation.mdx @@ -39,6 +39,12 @@ Cloudflare only serves stale content during revalidation if your origin includes If your origin sets `stale-while-revalidate` but you want to override it, you can disable stale serving through the [Serve stale content while revalidating](/cache/how-to/cache-rules/settings/#serve-stale-content-while-revalidating) setting in Cache Rules. Directives like `must-revalidate` and `no-cache` also prevent stale content from being served when [Origin Cache Control](/cache/concepts/cache-control/#enable-origin-cache-control) is enabled. For all available options, refer to [Cache-Control directives](/cache/concepts/cache-control/#cache-control-directives). +:::caution[`s-maxage` disables `stale-while-revalidate`] +The `s-maxage` directive implies `proxy-revalidate` semantics per [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-4), which prohibits shared caches from serving stale content. If your origin sends `s-maxage` alongside `stale-while-revalidate`, Cloudflare will not serve stale content — requests will return `EXPIRED` instead of `UPDATING`. + +To use `stale-while-revalidate` with a different edge TTL than browser TTL, configure your origin to send `max-age` with `stale-while-revalidate` (without `s-maxage`), then use [Edge Cache TTL](/cache/how-to/cache-rules/settings/#edge-ttl) in Cache Rules to set a separate TTL for Cloudflare. +::: + ## Smart revalidation towards users When both [`Last-Modified`](https://datatracker.ietf.org/doc/html/rfc7232?cf_history_state=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A15%2C%22targetId%22%3A%226C8153BAEF7BC0C5A331E28F8BCF1ABA%22%7D#section-2.2) and [`Etag`](https://datatracker.ietf.org/doc/html/rfc7232?cf_history_state=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A13%2C%22targetId%22%3A%226C8153BAEF7BC0C5A331E28F8BCF1ABA%22%7D#section-2.3) headers are absent from the origin server response, Smart Edge Revalidation will use the time the object was cached on Cloudflare's global network as the `Last-Modified` header value. When a browser sends a revalidation request to Cloudflare using `If-Modified-Since` or `If-None-Match`, our global network can answer those revalidation questions using the `Last-Modified` header generated from Smart Edge Revalidation. In this way, our global network can ensure efficient revalidation even if the headers are not sent from the origin.