new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Cloudflare Workers · all subjects

caching/cache-control

15 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Cache-Control directives determine cacheability

The `Cache-Control` header (and `cdn-cache-control`, `cloudflare-cdn-cache-control`) set on responses determine whether and how long Cloudflare caches them. Standard HTTP `Cache-Control` directives follow RFC 9111 semantics.

RFC 9111 heuristic freshness defaults for cacheable status codes

If a response has no `Cache-Control` header and no `Expires` header, Cloudflare applies RFC 9111 heuristic freshness with these per-status default TTLs: 200/203/204 (7200 seconds = 2 hours), 300/301 (1200 seconds = 20 minutes), 404/410 (180 seconds = 3 minutes), 405/414/501 (60 seconds = 1 minute). Other status codes are not cached by default. To prevent caching, return `Cache-Control: no-store` or `private` explicitly.

Cache Deception Armor protects against cache poisoning

When responses fall back to heuristic freshness (no `Cache-Control` set), Workers Caching runs Cache Deception Armor to defend against cache deception attacks. It only inspects responses with `Content-Type` starting with `text/` or `application/`. If the request URI has a file extension mapping to a known MIME type and the actual `Content-Type` does not match, the response is not cached and `Cf-Cache-Status` is `BYPASS`. For example, `/style.css` with `Content-Type: text/html` will bypass. Responses with other content types and requests without file extensions are not subject to the check. Any explicit `Cache-Control` directive skips Cache Deception Armor entirely.

Use max-age to control freshness window

The `max-age` directive controls how long a response is treated as fresh. For example, `Cache-Control: public, max-age=3600` caches the response for 1 hour at both Cloudflare's edge and in browsers.

Use stale-while-revalidate for low-latency refreshes

The `stale-while-revalidate` directive lets Cloudflare return a stale cached response immediately while refreshing it in the background. For example, `Cache-Control: public, max-age=600, stale-while-revalidate=60` keeps the response fresh for 10 minutes and may serve it stale for up to 1 minute while a background revalidation runs.

Directives that disable stale-while-revalidate

If the response includes `s-maxage`, `must-revalidate`, or `proxy-revalidate`, the stale-serving behavior is disabled and Cloudflare will block on fresh revalidation when the response expires. The same applies to `stale-if-error`. This follows RFC 9111 §4.2.4. To use `stale-while-revalidate` at the edge, use `max-age` for the freshness window, not `s-maxage`. If a longer edge TTL than browser TTL is needed, use `cdn-cache-control` for the edge directive.

TTL and stale-while-revalidate strategy for mostly static content

For mostly static content with small tolerance for staleness, use a short `max-age` (for example, 60 seconds) and a longer `stale-while-revalidate` window (for example, 3600 seconds). Most requests are HITs; occasional requests trigger a background refresh.

TTL and stale-while-revalidate strategy for high-traffic endpoints

For "always serve from cache" on high-traffic endpoints, use `max-age=0, stale-while-revalidate=<large>`. Every request returns the previously cached response immediately and triggers a background refresh. The Worker runs once per request to revalidate, so CPU costs are close to running every time. Freshness drops as request volume drops.

Serve stale on error with stale-if-error

The `stale-if-error` directive lets Cloudflare return a previously cached response when the Worker fails while refreshing an expired cache entry. This occurs when the Worker throws, times out, or returns a 5xx response. Cloudflare serves the last successful cached response (with `Cf-Cache-Status: STALE`) for up to the `stale-if-error` window. A true cache miss cannot benefit from `stale-if-error` because there is nothing stale to serve.

Default stale-if-error behavior when not set

If `stale-if-error` is not set explicitly and the response does not carry `s-maxage`, `must-revalidate`, or `proxy-revalidate`, Cloudflare's default is to serve stale responses on Worker error indefinitely (as long as the cached entry has not been purged). This aids resilience but can mask real failures. To surface Worker errors to clients quickly, set `stale-if-error=0`. If the response carries `s-maxage`, `must-revalidate`, or `proxy-revalidate`, `stale-if-error` is disabled and Worker errors flow through to clients immediately.

Cache header precedence order

When multiple cache headers are present, precedence is: 1. `cloudflare-cdn-cache-control` (Cloudflare-specific, highest precedence, consumed by Cloudflare and stripped from response to clients), 2. `cdn-cache-control` (standard header for CDN-only directives, respected by Cloudflare and passed through to downstream CDNs), 3. `Cache-Control` (standard HTTP header, respected by Cloudflare and passed through to clients). Use `cloudflare-cdn-cache-control` for longer edge TTL than exposed to browsers without leaking the directive downstream.

Override Cache-Control via cf.cacheControl in ctx.exports calls

When one entrypoint invokes another cached entrypoint through `ctx.exports`, the calling entrypoint can supply the `Cache-Control` directive by setting `cf.cacheControl` on the request. The callee does not need to set its own `Cache-Control`. Cloudflare treats `cf.cacheControl` as a trusted directive following standard `Cache-Control` semantics. This lets the caller decide caching policy without modifying the callee's code. `cf.cacheControl` is honored only for calls within the same account and has no effect on eyeball requests.

Automatic cache bypass conditions

Workers Caching inherits Cloudflare's standard cache bypass rules. Most common triggers: response includes a `Set-Cookie` header (unless `Cache-Control` includes `private="set-cookie"` or `no-cache="set-cookie"`), request includes an `Authorization` header (response only stored if `Cache-Control` includes `public`, `must-revalidate`, or `s-maxage`), response `Cache-Control` includes `private` or `no-store`. When any apply, `Cf-Cache-Status` is `BYPASS` and the Worker runs on every request.

no-cache does not bypass the cache

`Cache-Control: no-cache` does not bypass the cache. The response is stored but treated as stale immediately. Behavior depends on accompanying directives: `no-cache` alone triggers inline revalidation (Worker invoked before serving), `no-cache, stale-while-revalidate=N` serves cached body immediately and refreshes in background. In both cases, the Worker is invoked on every request and CPU time is billed. The cached body is preserved across revalidations.

Status codes never cached

Status codes 520–526 (Cloudflare failsafe responses) are treated as transient errors and never cached, even with explicit `Cache-Control` directives.

Give your agent this brain