---
title: "CDN cache misses, measured: 408,000 requests across 47 Cloudflare colos — warmup.rocks"
description: "Original data from 48 hours of cache warming: a cache miss is 3.5× slower than a hit at the median (878 ms vs 253 ms), and steady-state miss rates vary from 0.0% to 9.4% between Cloudflare colos. Full methodology included."
canonical: https://warmup.rocks/blog/cdn-cache-miss-data
---

Data

# CDN cache misses, measured: 408,000 requests across 47 Cloudflare colos

July 2026 · 8 min read · [← All posts](https://warmup.rocks/blog/)

Most articles about cache hit ratios quote someone else's benchmark. This one doesn't. Over 48 hours in July 2026 our warmer sent **408,323 requests** to 292 URLs across three production sites, routed through residential proxies so each request landed on a different Cloudflare data center — **47 distinct colos** in total. Every response's [`cf-cache-status`](https://warmup.rocks/blog/cf-cache-status) header and response time went into a database. Here is what the raw data says about cold caches, and about a few things we didn't expect.

## How much slower is a cache miss, really?

A cache miss is not a rounding error. In our steady-state data (after the initial warm-in, 263,030 successful requests), the median response time for a **HIT was 253 ms**; the median **MISS took 878 ms** — **3.5× slower**. The gap widens in the tail: at the 90th percentile a hit came back in 1,011 ms while a miss took 2,399 ms. A miss means the edge has to fetch from the origin — TLS handshake, origin render, transfer — before the visitor gets a byte, and that cost lands directly on [Time to First Byte](https://warmup.rocks/blog/time-to-first-byte).

| Percentile | HIT | MISS | Miss penalty |
| --- | --- | --- | --- |
| p25 | 169 ms | 535 ms | 3.2× |
| p50 (median) | 253 ms | 878 ms | 3.5× |
| p75 | 610 ms | 1,634 ms | 2.7× |
| p90 | 1,011 ms | 2,399 ms | 2.4× |

One honest caveat about the absolute numbers: our requests travel through residential proxies, which adds overhead a normal visitor doesn't have. The absolute milliseconds are therefore pessimistic — but the _relative_ HIT-vs-MISS gap is real, because both request types carry the same proxy overhead. If anything, the gap understates what your visitors feel, since their hits would be even faster.

## What does "warming in" look like?

The first hours of the measurement window are a textbook cold start: the caches were empty, and the miss rate in the first warming passes ran between **95% and 99%**. Within roughly twelve hours of scheduled warming the picture inverted completely — from July 15, 18:00 onward the aggregate miss rate settled at **1.0%** (2,759 misses out of 265,275 requests), a steady-state hit ratio of **99.0%**.

That number needs context: it's the hit ratio _the warmer itself_ observes, which is precisely the point of warming. Every one of those hits is an edge location where the next real visitor gets the 253 ms experience instead of the 878 ms one. Without warming, the long tail of your URLs sits cold at most locations most of the time — a dynamic we covered in [our cache hit ratio guide](https://warmup.rocks/blog/cache-hit-ratio).

## The finding we didn't expect: colos evict at wildly different rates

The same URLs, the same TTLs, the same warming schedule — and yet the steady-state miss rate varies by **two orders of magnitude** between data centers. European colos held nearly everything: Milan, Lisbon, London, Istanbul, Warsaw and a dozen others showed **0.0–0.1% misses**. Meanwhile the periphery kept forgetting:

| Colo | Requests | Steady-state miss rate |
| --- | --- | --- |
| Larnaca (LCA) | 8,248 | 9.4% |
| Tokyo (NRT) | 4,241 | 8.6% |
| Sydney (SYD) | 8,420 | 4.3% |
| Washington (IAD) | 11,895 | 3.7% |
| Singapore (SIN) | 9,358 | 3.3% |
| Santiago (SCL) | 6,346 | 2.3% |
| Vienna (VIE) | 25,192 | 0.05% |
| Amsterdam (AMS) | 10,390 | 0.02% |
| Milan (MXP) | 9,162 | 0.00% |

Why? Cloudflare's edge caches are not a promise — they're best-effort storage under **cache pressure**. A colo serving enormous volumes of other customers' content evicts less-requested objects sooner. Distance from our origins (Europe) plays a role too: colos far from the origin's region see less organic traffic for these sites, so warmed objects age out before anyone re-requests them. The practical consequence is uncomfortable for anyone who measures caching from a single location: **your hit ratio is not one number — it's a per-colo distribution**, and the locations where your cache is coldest are exactly the ones farthest from your origin, where a miss hurts the most.

## What this means if you run a site behind a CDN

-   **Measure per location, not from your desk.** A curl from your office tells you about one colo out of hundreds. Our [free cache checker](https://warmup.rocks/cache-checker) tests from multiple regions.
-   **Expect the far edge to go cold first.** If your customers are in Sydney and your origin is in Frankfurt, the Sydney colo is both your worst hit ratio _and_ your worst miss penalty. That's the location that benefits most from warming — one reason [single-server warming scripts fall short](https://warmup.rocks/blog/cloudflare-cache-warming).
-   **Re-warm on a schedule that matches eviction, not just TTL.** Larnaca losing 9% of objects between hourly passes means eviction there outpaces a naive TTL calculation. Where those numbers matter, warm more often.
-   **Check `cf-cache-status`, don't assume.** UPDATING and EXPIRED showed up in our data too (2,245 and 3 responses respectively) — each status has a different fix, listed in [our cf-cache-status guide](https://warmup.rocks/blog/cf-cache-status).

## Methodology, so you can judge the data

-   **Window:** July 15–17, 2026 (48 hours); steady-state figures exclude the initial warm-in and cover July 15, 18:00 UTC onward.
-   **Volume:** 408,323 requests total, 292 unique URLs, three production sites (HTML pages, all behind Cloudflare with [cache-everything page rules or equivalent](https://warmup.rocks/docs/cdns)).
-   **Distribution:** residential proxies in 40+ countries; the colo for every response was read from the response headers, 47 distinct colos observed.
-   **Counting:** only HTTP 200 responses; miss rate = MISS / (all cache statuses); response time measured request-start to completion, including proxy overhead (identical for HIT and MISS).
-   **Bias to be aware of:** this is data from a cache-warming service, measured by that service. The warm-in curve and per-colo eviction data don't depend on that; the 99% steady-state figure describes warmed sites by definition.

We'll re-run this analysis with a longer window and more sites as the dataset grows. If you want us to break down something specific — per-CDN comparisons, mobile variants, asset types — reply to any of our emails; they land in a human inbox.
