Cache status headers

Read X-Cache-Status, the standard Cache-Status header and Age to see whether the edge served a response from cache and why not.

On this page

Every response of a name with the cache on carries two headers that say what the cache did, plus Age when it served a stored copy.

curl -sI https://www.example.com/app.css | grep -i -E 'x-cache-status|cache-status|age'

X-Cache-Status

Uses the values you may know from other CDNs:

ValueMeaning
HITServed from the edge cache.
MISSEligible but not cached yet: fetched from the origin and stored when allowed.
EXPIREDThe stored copy had expired; a fresh one came from the origin.
REVALIDATEDThe stored copy had expired; the origin confirmed it with 304.
UPDATINGAn expired copy served while it refreshes in the background (stale-while-revalidate).
STALEAn expired copy served because the origin failed.
BYPASSEligible, but the response couldn't be stored (for example Set-Cookie or private).
DYNAMICNot eligible: the cache wasn't looked up (HTML without a rule, a bypass rule, a POST…).

No header at all means the cache wasn't involved: the answer came from the WAF, a challenge, the access gate or an edge redirect.

Cache-Status

The standard header from RFC 9211, with the reason in detail:

Cache-Status: OpenWAF; hit
Cache-Status: OpenWAF; fwd=uri-miss; stored
Cache-Status: OpenWAF; fwd=stale; fwd-status=304
Cache-Status: OpenWAF; fwd=bypass; detail=set-cookie
detailWithMeaning
storedMISS, EXPIREDThe response was stored.
not-stored, busyMISSStorable, but this copy wasn't stored.
set-cookieBYPASSThe response sets a cookie.
private, no-storeBYPASSThe origin's Cache-Control forbids storing it.
authBYPASSThe request had Authorization and the response didn't allow sharing it.
varyBYPASS, DYNAMICAn unsupported Vary, or the request carried a header of a rule's vary_bypass_if_present.
sizeBYPASSLarger than the maximum object size.
deceptionBYPASSBlocked by the cache deception armor.
statusBYPASSThe status code can't be cached.
uncacheableBYPASSNo freshness information and no default TTL applies (for example HTML made eligible by a rule without a TTL).
personalBYPASSA personal document requested with cookies or Authorization, without explicit freshness.
ruleBYPASS, DYNAMICA rule's status TTL of -1, or a bypass rule.
invalid, encodingBYPASSAn invalid Cache-Control, or a content encoding other than gzip or Brotli.
extensionDYNAMICThe extension isn't in the default list and no rule makes the path eligible.
disabled, dev-modeDYNAMICThe cache is off, or development mode is on.
method, upgrade, bodyDYNAMICNot a GET/HEAD, a WebSocket upgrade, or a request with a body.
path, query, keyDYNAMICAn ambiguous path, a query with caching level No query string, or a key that is too long.

Age

Sent on HIT, STALE, UPDATING and REVALIDATED: the seconds since the object was stored or last revalidated. An Age sent by your origin on a response that wasn't cached is forwarded unchanged.

Headers the edge removes

OpenWAF-CDN-Cache-Control and Cache-Tag are meant for the edge only and are removed before the response reaches the visitor. An X-Cache-Status sent by your origin is replaced.

Last updated:

↑↓ to navigate↵ to openesc to close