What Cloudflare caches — and why

Caching Lab

Every row below is a real file on your origin, each sent with a different Cache-Control header (or a different file extension). Press Fetch ×3 on each and watch the cf-cache-status header to see what Cloudflare decided.

How to read cf-cache-status

HITServed from Cloudflare's edge cache — your origin was never touched.
MISSNot in edge cache; Cloudflare fetched it from origin (and now usually stores it).
EXPIREDWas cached, but its TTL ran out — Cloudflare went back to origin.
DYNAMICCloudflare isn't caching this at all (e.g. .html, or no cache rule says otherwise).
BYPASSThe origin's headers (or a Cloudflare rule) told the edge not to cache.
REVALIDATEDCloudflare checked with origin (304 Not Modified) and served the cached copy.

These headers only exist when the request goes through Cloudflare. Direct to origin, there is nothing to see — that's the banner above.

Experiment 1 — headers & file types

Note: each lab fetch carries a unique query string so your browser cache can't interfere — only Cloudflare answers. With the zone set to Caching Level Ignore Query String (Caching → Configuration), HITs appear from the second fetch on. First-ever fetch of a file is always a MISS — that's the cache being filled.

Test fileExpectedResults

Experiment 2 — query strings & cache keys

Does ?a=1 and ?a=2 mean one cache entry or two? Warm one, then fetch the other.

Then flip the setting in Cloudflare (Caching → Configuration → Caching Level: Standard vs Ignore Query String), purge the cache, and run it again — the answer changes.

Things to try next