---
description: Diagnose why a URL you expected to be cached is served from the origin, using the cf-cache-status header to isolate the cause.
title: Investigate uncached responses
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cache/llms.txt  
> Use this file to discover all available pages before exploring further.

# Investigate uncached responses

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/troubleshooting/investigating-uncached-responses/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

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](#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](#bypass--origin-response-is-not-cacheable).
* `MISS` on 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](#repeated-miss--cacheable-but-not-in-cache).

For any other status, refer to [Cache responses](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/) for the full list.

Note

Cloudflare returns `BYPASS` — not `MISS` — for responses it chooses not to cache. `MISS` is reserved for cacheable responses that were not in cache at request time. Refer to the [BYPASS status changelog](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/changelog/post/2026-05-26-bypass-status-for-uncacheable-responses/) for context.

## Before you start

A recent [Purge Everything](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/), [purge by URL](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/), [purge by prefix](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/purge-cache/purge%5Fby%5Fprefix/), [purge by tag](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/), or [purge by hostname](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/purge-cache/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.

## DYNAMIC — request not eligible for cache

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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions) list** — for example, `.html` or a JSON API response — and no rule enables caching for it. Add a [Cache Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) with **Eligible for cache** set to _Yes_.
* **A rule instructs Cloudflare to bypass cache.** Check whether a Cache Rule with the [Bypass cache](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/settings/#bypass-cache) setting, or a legacy `Cache Level: Bypass` [Configuration Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/configuration-rules/) or [Page Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/page-rules/), matches the URL. Use [Rule Trace](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/trace-request/) to confirm which rules apply.
* **The request method is not `GET` or `HEAD`.** Cloudflare only caches these two methods.
* **[Development Mode](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/reference/development-mode/) is enabled on the zone.** Development Mode suspends cache for three hours and returns `DYNAMIC` for every response.

Once the request is eligible, subsequent responses reflect the response-time decision (`HIT`, `MISS`, `BYPASS`, and so on).

## BYPASS — origin response is not cacheable

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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/default-cache-behavior/#cacheable-size-limits) for your plan.** Split the object into smaller assets, or move to a plan with a higher limit. [R2](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/r2/) is an origin storage alternative — it does not raise the CDN cacheable size limit.
* **The origin returned `no-store` or bare `private` in a `Cloudflare-CDN-Cache-Control` or `CDN-Cache-Control` header.** Cloudflare evaluates these headers ahead of `Cache-Control`, in the precedence `Cloudflare-CDN-Cache-Control` \> `CDN-Cache-Control` \> `Cache-Control`. An origin returning `Cache-Control: public, max-age=3600` together with `CDN-Cache-Control: no-store` produces `BYPASS`. Cloudflare does not forward `Cloudflare-CDN-Cache-Control` to the client, so it is not visible in the response — if you see `BYPASS` without a `CDN-Cache-Control` header, check what the origin actually sent, or have the origin drop the header and retest. A [Cache Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) with an [Edge Cache TTL](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) setting that ignores origin cache-control overrides both directives. Refer to [CDN-Cache-Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cdn-cache-control/) for the precedence rules.
* **`no-cache`, `max-age=0`, or `s-maxage=0` in `Cloudflare-CDN-Cache-Control` or `CDN-Cache-Control` do not produce `BYPASS`.** They produce `MISS` on the first request, then [REVALIDATED](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#revalidated) or [EXPIRED](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#expired) on subsequent requests.
* **The origin returned `Cache-Control: no-store` or bare `private`.** These directives block caching in either [Origin Cache Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) 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 with `no-store` plus that Edge TTL setting is cached.
* **The origin returned `Cache-Control: no-cache`, `max-age=0`, or `s-maxage=0`, and [Origin Cache Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/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, producing [REVALIDATED](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#revalidated) or [EXPIRED](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#expired). Refer to [Understand no-store and no-cache directives](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-control/#understand-no-store-and-no-cache-directives) and the [Conditions](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-control/#conditions) table.
* **The origin returned a `Set-Cookie` header.** By default, Cloudflare does not cache responses that include `Set-Cookie`. To cache the response, use one of the following:

  * Set an explicit Edge TTL on a [Cache Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) 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"` or `no-cache="Set-Cookie"`. Cloudflare drops the named header and caches the rest.
  * Strip `Set-Cookie` before the cache decision, using a [Response Header Modification Transform Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/transform/response-header-modification/).
  * On Enterprise plans with [Origin Cache Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-control/) disabled, Cloudflare strips `Set-Cookie` and caches the response under the default cache level. A `Cache Level: Cache Everything` [Page Rule](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/page-rules/) or a Cache Rule with **Eligible for cache** set to _Yes_ — either without an explicit Edge TTL — overrides this and returns `BYPASS`.  
Refer to [Interaction of Set-Cookie response header with Cache](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-behavior/#interaction-of-set-cookie-response-header-with-cache) for the full matrix.
* **The origin returned `Vary: *`.** This value always bypasses cache, regardless of other configuration.
* **The request included an `Authorization` header and [Origin Cache Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-control/) is enabled** (the default on Free, Pro, and Business plans). In that mode, the response is cacheable only if `Cache-Control` also includes `public`, `s-maxage`, or `must-revalidate`. On Enterprise plans with Origin Cache Control disabled, `Authorization` does not by itself prevent caching.

Refer to [BYPASS](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#bypass) for the reference definition of this status.

## Repeated MISS — cacheable but not in cache

`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.

### Cache key variance

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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) or [Cache Key Settings](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-keys/#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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-keys/) includes a cookie or header with a value that changes per user.** The [Create custom cache keys](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-keys/#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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/examples/cache-device-type/) classifies clients differently than expected**, particularly for bots or clients with unusual `User-Agent` values.
* **[Vary in Cache Rules](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/settings/#vary) is configured** for a header, the origin lists that header in its `Vary` response header, and the action is `normalize` or `passthrough`. Each response variant is stored under a separate key. When the header has high cardinality — for example, an unnormalized `Accept-Language` value or a per-user header — the practical hit rate drops. The `bypass` action prevents caching entirely.

Two identical requests produce the same cache key and cannot reveal variance. To diagnose, use [Rule Trace](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/rules/trace-request/) 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.

### Eviction and low-traffic assets

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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/tiered-cache/) or [Cache Reserve](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/advanced-configuration/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.

## Confirm the response reaches cache

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: HIT` and an `Age` header that increases on subsequent requests. `Age` is absent on the first request that fills the local data center's cache from an upper tier via [Tiered Cache](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/tiered-cache/) — the `HIT` reflects the upper tier, but the local data center has not served it from cache yet. Subsequent requests include `Age`, and with Tiered Cache the value can already be large because it reflects the object's age in Cloudflare's network-wide cache.
* **Origin returns `Cache-Control: no-cache` with [Origin Cache Control](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-control/) enabled:** `cf-cache-status: REVALIDATED` when the origin confirms the cached copy is unchanged, or [EXPIRED](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/#expired) when the origin returns new content. Both indicate the response is cached. `must-revalidate` on 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.

## Related resources

* [Cache responses](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/cache-responses/) — reference for every `cf-cache-status` value.
* [Default cache behavior](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/concepts/default-cache-behavior/) — when Cloudflare caches successfully by default.
* [Cache Rules](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/how-to/cache-rules/) — configure Edge TTL, eligibility, and cache key.
* [Cache Analytics](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/cache/performance-review/cache-analytics/) — measure hit rate and identify low-performing URLs.

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cache/troubleshooting/investigating-uncached-responses/#page","headline":"Investigate uncached responses · Cloudflare Cache (CDN) docs","description":"Diagnose why a URL you expected to be cached is served from the origin, using the cf-cache-status header to isolate the cause.","url":"https://developers.cloudflare.com/cache/troubleshooting/investigating-uncached-responses/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
