If a URL you expected to be cached is served from the origin every time, the cf-cache-status response header identifies which cache decision Cloudflare made. Fetch the URL, inspect the header, and follow the section that matches the value you see:
DYNAMIC— Cloudflare decided the request was not eligible for cache before it looked in the cache. Refer to DYNAMIC — request not eligible for cache.BYPASS— Cloudflare was ready to cache the response, but the origin response or configuration prevented it. Refer to BYPASS — origin response is not cacheable.MISSon multiple consecutive requests from the same client — the response is cacheable but keeps missing the cache. Refer to Repeated MISS — cacheable but not in cache.
For any other status, refer to Cache responses for the full list.
A recent Purge Everything, purge by URL, purge by prefix, purge by tag, or purge by hostname clears the cache. The next request in each data center repopulates cache and returns MISS before subsequent requests return HIT. If a purge ran recently, wait for the cache to repopulate before continuing.
Cloudflare made the "do not cache" decision at request time, before looking in the cache. Common causes:
- The file extension is not in the default cached file extensions list — for example,
.htmlor a JSON API response — and no rule enables caching for it. Add a Cache Rule with Eligible for cache set to Yes. - A rule instructs Cloudflare to bypass cache. Check whether a Cache Rule with the Bypass cache setting, or a legacy
Cache Level: BypassConfiguration Rule or Page Rule, matches the URL. Use Rule Trace to confirm which rules apply. - The request method is not
GETorHEAD. Cloudflare only caches these two methods. - Development Mode is enabled on the zone. Development Mode suspends cache for three hours and returns
DYNAMICfor every response.
Once the request is eligible, subsequent responses reflect the response-time decision (HIT, MISS, BYPASS, and so on).
The request was eligible for cache, but the origin response or configuration prevented Cloudflare from storing it. Common causes:
-
The response exceeds the cacheable size limit for your plan. Split the object into smaller assets, or move to a plan with a higher limit. R2 is an origin storage alternative — it does not raise the CDN cacheable size limit.
-
The origin returned
Cache-Control: no-storeor bareprivate. These directives block caching in either Origin Cache Control mode by default. Two exceptions:Cache-Control: private="<header>"with field names remains cacheable — Cloudflare drops only the named headers. And a Cache Rule with an Edge TTL that ignores origin cache-control (Edge TTL → Ignore cache-control header and use this TTL or Status code TTL) overrides both directives, so a response withno-storeplus that Edge TTL setting is cached. -
The origin returned
Cache-Control: no-cache,max-age=0, ors-maxage=0, and Origin Cache Control is disabled (the default on Enterprise plans). With Origin Cache Control enabled (the default on Free, Pro, and Business plans), these directives cause Cloudflare to cache and revalidate the response instead, producingREVALIDATEDorEXPIRED. Refer to Understandno-storeandno-cachedirectives and the Conditions table. -
The origin returned a
Set-Cookieheader. By default, Cloudflare does not cache responses that includeSet-Cookie. To cache the response, use one of the following:- Set an explicit Edge TTL on a Cache Rule using Edge TTL → Ignore cache-control header and use this TTL or Status code TTL. Cloudflare ignores the origin's directives, strips
Set-Cookie, and caches the response. - Have the origin return
Cache-Control: private="Set-Cookie"orno-cache="Set-Cookie". Cloudflare drops the named header and caches the rest. - Strip
Set-Cookiebefore the cache decision, using a Response Header Modification Transform Rule. - On Enterprise plans with Origin Cache Control disabled, Cloudflare strips
Set-Cookieand caches the response under the default cache level. ACache Level: Cache EverythingPage Rule or a Cache Rule with Eligible for cache set to Yes — either without an explicit Edge TTL — overrides this and returnsBYPASS.
Refer to Interaction of
Set-Cookieresponse header with Cache for the full matrix. - Set an explicit Edge TTL on a Cache Rule using Edge TTL → Ignore cache-control header and use this TTL or Status code TTL. Cloudflare ignores the origin's directives, strips
-
The origin returned
Vary: *. This value always bypasses cache, regardless of other configuration. -
The request included an
Authorizationheader and Origin Cache Control is enabled (the default on Free, Pro, and Business plans). In that mode, the response is cacheable only ifCache-Controlalso includespublic,s-maxage, ormust-revalidate. On Enterprise plans with Origin Cache Control disabled,Authorizationdoes not by itself prevent caching.
Refer to BYPASS for the reference definition of this status.
MISS on the first request in each data center is expected — that request populates the cache. If the same URL keeps returning MISS across consecutive requests, one of the following is happening.
Cloudflare builds the cache key from the origin scheme, host, path, and query string by default. Cookies, headers, and device type can also contribute when configured. The scheme in the cache key is the scheme Cloudflare uses to reach the origin, not the scheme the client used — a zone with a single origin scheme serves HTTP and HTTPS client requests from the same cache entry.
If each real client request produces a different key, the cache never sees a repeat and every request is a MISS. Common patterns:
- Query parameters that change per request — session IDs, timestamps, or marketing tags such as
utm_*. By default, every unique query string is a separate cache entry. Configure Cache Rules or Cache Key Settings to exclude or ignore parameters whose value changes per request. Sorting only canonicalizes parameter order — use it when requests differ only in the order of parameters, not when the values differ. - A custom cache key includes a cookie or header with a value that changes per user. The Create custom cache keys section warns that custom keys "may reduce your cache hit rate and result in cache sharding" — this is the same behavior.
- Cache by device type classifies clients differently than expected, particularly for bots or clients with unusual
User-Agentvalues. - Vary in Cache Rules is configured for a header, the origin lists that header in its
Varyresponse header, and the action isnormalizeorpassthrough. Each response variant is stored under a separate key. When the header has high cardinality — for example, an unnormalizedAccept-Languagevalue or a per-user header — the practical hit rate drops. Thebypassaction prevents caching entirely.
Two identical requests produce the same cache key and cannot reveal variance. To diagnose, use Rule Trace to see the applied cache-key configuration and Vary action for the URL, then compare that against the request attributes (query string, cookies, headers, device type) that differ between real client requests.
Low-traffic assets can be evicted from the cache before the next request arrives. If two consecutive requests to the same URL from the same data center both return MISS, enable Tiered Cache or Cache Reserve to retain long-tail content longer.
If your requests reach different Cloudflare data centers, each produces its own first-request MISS. Compare the data center code — the last three characters of the cf-ray header — to confirm two responses came from the same data center. Different client networks can still reach the same data center, so a network change does not guarantee a different location.
After adjusting configuration, request the URL twice from the same client and verify the expected outcome for your configuration:
- Fresh, positive Edge TTL:
cf-cache-status: HITand anAgeheader that increases on subsequent requests.Agemay be absent on the first lower-tier request that populates the local cache from a tiered cache fill (CacheTieredFill=true). - Origin returns
Cache-Control: no-cachewith Origin Cache Control enabled:cf-cache-status: REVALIDATEDwhen the origin confirms the cached copy is unchanged, orEXPIREDwhen the origin returns new content. Both indicate the response is cached.must-revalidateon its own does not force revalidation on every request — it only prevents serving stale content after the freshness TTL expires.
If the response is still MISS or BYPASS after these checks, capture two full responses (request and response headers, including cf-ray values) and open a support case. The cf-ray values are required to trace the request through the Cloudflare network.
- Cache responses — reference for every
cf-cache-statusvalue. - Default cache behavior — when Cloudflare caches successfully by default.
- Cache Rules — configure Edge TTL, eligibility, and cache key.
- Cache Analytics — measure hit rate and identify low-performing URLs.