---
title: Is my CDN actually caching? How to check with the Global CDN Checker
description: You pay for a CDN, yet users in one region say the site is slow, and you can't tell whether the edge is serving from cache or going back to your origin every time. To check if your CDN is caching, request the same URL several times from many regions and read the cache status each edge reports. Here's how with the free Global CDN Checker, a real run across 20 locations, and the curl commands that show the same headers.
canonical: https://watchfor.io/blog/how-to-check-if-your-cdn-is-caching
---

# Is my CDN actually caching? How to check with the Global CDN Checker

2026-10-04 · WatchFor Team · Guides · guides, cdn, performance

You pay for a CDN, yet users in one region say the site is slow, and you can't tell whether the edge is serving from cache or going back to your origin every time. To check if your CDN is caching, request the same URL several times from many regions and read the cache status each edge reports. Here's how with the free Global CDN Checker, a real run across 20 locations, and the curl commands that show the same headers.

To check whether your CDN is caching a URL, request it more than once from
several regions and read the cache headers each edge sends back, such as
`x-cache: HIT` or `cf-cache-status: HIT`. A `HIT` means the edge answered
from its own copy; a `MISS` on every request means each visitor's request
goes back to your origin. One request from one place isn't enough: the first
request to a cold edge is always a miss.

The free [Global CDN Checker](/cdn-checker) does this from every WatchFor
probe location at once, three requests each, identifies the CDN, and grades
the result. No signup.

## What this tool answers

*Which CDN serves this URL, and is each region getting it from cache?*
Reach for it when users in one part of the world report slowness, after
changing cache rules or `Cache-Control` headers, after moving to a new CDN
or host, or when your origin's load doesn't drop the way it should with a
CDN in front. It also tells you which edge answered in each region, which
is often the real explanation for a slow country.

## A real example

### Checking if your CDN is caching when one region says the site is slow

The report: the site feels fast in the office, and a colleague in another
region says images load slowly. Is the CDN caching there, or is every
request going back to the origin? We checked a static asset on a
CDN-backed site, `playwright.dev/img/playwright-logo.svg`, with the
[Global CDN Checker](/cdn-checker):

![The Global CDN Checker report for playwright.dev/img/playwright-logo.svg: grade A+ at 100/100, Fastly via GitHub with high confidence, all 20 probe locations got a response, 100% of requests served from cache, edge p50 3 ms, first visit p50 12 ms, no problems found, and a world map where every location is green except Tel Aviv in amber](/blog/how-to-check-if-your-cdn-is-caching-report.webp)

**A+, served by Fastly via GitHub**, 20 of 20 locations answered, and
**100% of requests were cache hits**. The median edge took 3 ms to answer
and the median first visit took 12 ms. So caching is not the problem in any
region we tested.

The per-location table shows what the map summarises, including which edge
answered each probe:

![Per-location results: every location shows HIT HIT HIT. Cape Town is served by the CPT edge in 9 ms, Jakarta by SIN in 55 ms, Mumbai by BOM in 7 ms, Frankfurt by FRA in 10 ms, Vilnius by BER in 87 ms, and Tel Aviv by MXP with a 146 ms edge response and 224 ms to first byte](/blog/how-to-check-if-your-cdn-is-caching-locations.webp)

Every row is `HIT HIT HIT`. The one amber dot is **Tel Aviv**: the request
was answered by the `MXP` edge (Milan), with 36 ms for the TCP connection,
41 ms for TLS and 224 ms to the first byte. Vilnius went to Berlin (`BER`,
87 ms) and Jakarta to Singapore (`SIN`, 55 ms). In this run those probes
were answered by an edge in another country, so every request pays for the
extra distance, cached or not.

**The answer:** the CDN caches this file everywhere; the slow region is
about distance to the nearest edge the CDN picked, not about caching. For
your own site, that difference decides the fix. A `MISS` everywhere is a
configuration problem you can fix (cache headers, cookies, query strings).
A `HIT` served from far away is a CDN coverage or routing question for your
provider, or a reason to compare providers in that region.

## How to read the results

| What you see | What it means |
| --- | --- |
| **Grade (A+ … F)** | The overall delivery grade; open **How this grade was reached** for the exact deductions. |
| **Provider and confidence** | The CDN identified from headers, DNS and network evidence. "Fastly via GitHub" means GitHub Pages runs on Fastly. |
| **Locations** | How many probe locations got a response. |
| **Cache hits** | Share of all requests the edges reported as served from cache. "not published" when the CDN sends no cache header at all. |
| **Edge p50** | Median time the edge took to answer once the connection was open (first byte minus DNS, TCP and TLS). |
| **First visit p50** | Median time to first byte for a fresh visitor, connection setup included. |
| **Issues found** | Problems derived from the measurements, such as low hit ratio, regions behaving differently or errors. |
| **World view** | The same numbers on a map; switch between edge response, first visit and cache. Green under 100 ms, amber 100–200, orange 200–500, red above. |
| **Per location: Edge** | The edge that answered, usually an airport code from the CDN's own headers. |
| **Per location: Cache** | The verdict for each of the three requests: `HIT`, `MISS`, `EXPIRED`, `STALE`, `REVALIDATED`, `BYPASS`, `DYNAMIC` or `UNKNOWN`. |
| **Caching** | What the response allows: here `Cache-Control: max-age=600`, so shared caches may keep it for 600 seconds. |
| **Protocols** | IPv4, IPv6, HTTP/2, HTTP/3, TLS 1.3, Brotli and gzip as observed. This logo was served over HTTP/2 and HTTP/3 with gzip, not Brotli. |
| **Content consistency** | Whether every location got the same bytes. Here all 20 did. |

## More ways to use it

- **After a deploy, for stale assets.** If users still see old CSS, check
  the asset URL: a long `max-age` without a versioned file name means the
  edges are right to keep the old copy.
- **After changing cache rules.** A `BYPASS` or `DYNAMIC` on a static file
  usually means a cookie, an `Authorization` header or a page rule is
  stopping the cache.
- **Comparing a page and its assets.** HTML is often `DYNAMIC` by design
  while scripts and images should be `HIT`. Test both.
- **Before switching CDNs.** Run your busiest asset on the current setup,
  note which regions are served from far away, and compare after a trial.

## Tips and gotchas

- **The path matters.** `/` and `/static/app.js` usually have different
  rules. Test the URL you actually care about.
- **Three requests, three verdicts.** The first request to an edge may be a
  `MISS`; a `MISS` followed by `HIT`s is caching working as intended.
  [Why your CDN stopped caching](/blog/why-your-cdn-stopped-caching)
  explains why one request tells you nothing.
- **`UNKNOWN` isn't a failure.** Some CDNs publish no cache header at all;
  the ratio then reads "not published".
- **Edge choice is the CDN's decision.** Anycast and DNS steer each visitor
  to an edge; a probe in one city can land in another country, as Tel Aviv
  did. [Anycast explained](/blog/anycast-explained) covers how.
- **It fans out to every location.** One run is around 60 requests to the
  target, so the free checker is limited to a few runs per hour.
- **Results are one moment.** A cache that was just purged will show
  misses until traffic warms it up again.

## Check it from the command line too

Request the asset a few times and print the headers that matter:

```bash
for i in 1 2 3; do
  curl -s -o /dev/null -D - https://playwright.dev/img/playwright-logo.svg \
    | grep -iE '^(x-served-by|x-cache|cache-control):' | tr -d '\r' | tr '\n' ' '
  echo
done
```

```text
cache-control: max-age=600 x-served-by: cache-ber1080057-BER x-cache: MISS
cache-control: max-age=600 x-served-by: cache-dus1260037-DUS x-cache: HIT
cache-control: max-age=600 x-served-by: cache-dus1260023-DUS x-cache: HIT
```

From our machine, the first request hit a cold node in Berlin and missed;
the next two were answered from cache in Düsseldorf. That is the pattern
the checker reports per location: Fastly names the edge in `x-served-by`
and the verdict in `x-cache`. Cloudflare uses `cf-cache-status` and
`cf-ray`, CloudFront `x-cache` and `x-amz-cf-pop`. To see how long the
edge has held its copy, look at the `age` header, in seconds.

## Keep watching it

Caching breaks quietly: a new cookie, a header change at the origin or a
rule edit can turn every hit into a miss, and you only notice when the
origin's load or the bill rises. A [CDN monitor](/cdn-monitoring) checks
the URL on a schedule with two requests per check, tracks the cache hit
ratio and edge response time, and can alert when caching stops working,
the edge gets slow, the provider changes, or the edge returns errors.

## FAQ

**How do I know if my CDN is caching?**
Request the URL two or three times and look for a cache header such as
`x-cache: HIT`, `cf-cache-status: HIT` or a growing `age`. Check from more
than one region, because each edge has its own cache.

**What does x-cache: MISS mean?**
That edge didn't have the file and fetched it from the origin. One miss is
normal for a cold edge; misses on every request mean the response isn't
being cached, often because of `Cache-Control: private` or `no-store`,
cookies, or query strings. [Caching explained](/blog/caching-explained)
covers the headers.

**Why is my site slow in one country even with a CDN?**
Either that region's edge isn't caching (look for misses), or the nearest
edge the CDN picks is far away (look at which edge answered and the
connection time), as with Tel Aviv being served from Milan above.

---

Canonical page: https://watchfor.io/blog/how-to-check-if-your-cdn-is-caching · All articles: https://watchfor.io/blog/all.md · Site guide: https://watchfor.io/llms.txt
