CDN Cache Hit Ratio: How to Measure It

A CDN earns its place by answering from cache, close to the visitor, without asking your origin. The cache hit ratio is the share of requests where that actually happened — and it is the one CDN number no uptime check will ever show you.

What the ratio means

Every request that reaches a CDN edge ends one of two ways. Either the edge has a fresh copy and answers immediately — a hit — or it forwards the request to your origin and waits — a miss. The hit ratio is hits divided by all requests. A ratio near 100% on static assets is normal; a ratio near 0% means the CDN is adding a network hop and removing nothing.

Two outcomes sit in between. A revalidated response was in cache but stale, so the edge asked the origin whether it changed; the origin answered quickly, but it was still asked. A stale response was served from cache while the edge refreshed it in the background — the visitor did not wait on the origin. Responses the CDN marks as dynamic or bypass were never eligible for caching at all.

Reading the cache headers

Each CDN reports the result in its own header. The common ones:

  • Cloudflare — cf-cache-status: HIT, MISS, EXPIRED, REVALIDATED, DYNAMIC, BYPASS. The cf-ray header ends in the edge's airport code.
  • Amazon CloudFront — x-cache: Hit from cloudfront or Miss from cloudfront; x-amz-cf-pop names the edge.
  • Fastly — x-cache: HIT, MISS, one value per cache layer (shield, then edge); x-served-by lists the nodes.
  • Akamai — usually exposed through Server-Timing: cdn-cache; desc=HIT.
  • Vercel — x-vercel-cache; Netlify — the standard Cache-Status header.

Layered caches need care. When Fastly answers x-cache: HIT, MISS, the shield had a copy and the edge did not — the origin was never asked. Counting that as a miss understates what the CDN is doing for you.

Why a CDN misses on every request

  • The response says not to cache it — Cache-Control: private, no-store or max-age=0, often added by a framework default.
  • A cookie comes back — many CDNs will not cache a response that sets one.
  • The cache key is too fine — a Vary header on User-Agent, or query strings that change on every request, give every visitor their own cache entry.
  • The TTL is shorter than the traffic gap — a quiet page expires before its next visitor arrives.
  • Deploys purge everything — fine once, but a pipeline that purges on every commit keeps the cache permanently cold.

Measuring it over time

A single request tells you about one edge at one moment. The useful number is the ratio over days, measured the same way each time: request the same URL on a schedule, record hit or miss, and graph the share of hits. A drop from 95% to 10% after a deploy is a configuration regression, even though every request still returned 200.

Remember that each edge keeps its own cache. A scheduled check from one location measures the edge that location reaches; a path can be warm there and cold elsewhere. Real-user data that records the cache result per page view, where the CDN exposes it, covers the rest.

Finally, compare with the origin. Request the same path straight from the origin and compare time to first byte: that difference is what the CDN actually saves. If it is negative, the CDN is making that path slower.

Frequently Asked Questions

What is a good CDN cache hit ratio?

For static assets — images, scripts, stylesheets, fonts — above 90% is typical and achievable. For HTML pages it depends on how personalised they are; a fully dynamic page may correctly be 0%. What matters most is the trend: a sudden drop on a path that used to cache is a regression.

Does a cache miss mean my CDN is broken?

Not on its own. The first request to a quiet edge is always a miss, and some responses should never be cached. A miss on every request to a static path, over hours, is the signal worth acting on.

Can a CDN make my site slower?

Yes. A miss adds the edge-to-origin hop to a request that could have gone straight to the origin. With a poor hit ratio and an origin close to most visitors, time to first byte can get worse — which is why comparing the CDN with the origin directly is worth doing.

Why does curl show a hit when my visitors see misses?

You are reaching a different edge. Each edge location has its own cache, so a path you just warmed from your office is still cold in another region.

Stop checking this by hand

NetTests runs this kind of check on a schedule, stores historical results, and alerts your team the moment something changes.

Start monitoring free →
No credit card required  ·  Free plan available