CDN caching: how edge caches work, with Cloudflare rules
How edge caches decide hits and misses, what Cloudflare caches by default, cache rules for HTML, APIs and HLS, measuring hit ratio, and purging safely.
On this page 8 sections
CDN caching stores copies of your responses on edge servers close to your users, so most requests are answered nearby instead of travelling to your origin server. For each request the edge builds a cache key, usually from the URL, looks for a copy that is still fresh, and goes to the origin only on a miss. Your Cache-Control headers and the CDN's own rules decide what gets stored and for how long.
How a CDN edge cache works
- A student's request reaches a nearby edge data centre, through anycast routing or DNS.
- The edge computes the request's cache key and looks it up.
- On a hit, it serves the stored copy. On a miss, or when the stored copy has expired, it asks the origin (or revalidates with an ETag), stores the response if it is cacheable, and sends it to the student.
Two features decide how much traffic still reaches your origin:
- Request collapsing. When many requests for the same uncached object arrive together, the edge sends one to the origin and makes the rest wait for its response. Cloudflare does this per data centre with a cache lock, and CloudFront collapses simultaneous requests that share a cache key.
- Tiered caching. An edge that misses asks an upper-tier data centre before going to the origin, so only a few locations ever fetch from you. Without tiers, a new file first requested in 40 cities can cost up to 40 origin fetches; with tiers, it costs a handful. On Cloudflare, Tiered Cache with the Smart topology is available on every plan.
Cache keys and variants
The cache key decides which requests share a copy. Cloudflare's default key is the full URL, meaning scheme, host, path and query string, plus a few request headers such as Origin, which is there for CORS. Anything that makes URLs differ without changing the content splits your cache:
- Tracking parameters. /courses/?utm_source=whatsapp and /courses/?utm_source=telegram are two cache entries for one page.
- Per-student tokens. Signed video URLs often carry a token in the query string. If the token is part of the cache key, every student gets a private copy of every segment and the hit ratio collapses. Keep tokens out of the key and check them at the edge instead; our guide to signed URLs and hotlink protection covers the options.
- Vary headers. Vary: Cookie tells a cache that every distinct Cookie header needs its own copy. With analytics cookies on every request, that means almost no reuse.
Most CDNs let you change the key. On Cloudflare, the Ignore Query String caching level drops query strings for static file types, and Enterprise plans can build custom cache keys that include or exclude specific query parameters, headers and cookies.
What Cloudflare caches by default
This guide uses Cloudflare as its worked example because its defaults are publicly documented; other CDNs offer equivalent controls under different names. Cloudflare's default cache behaviour surprises many teams:
- It goes by file extension, not content type. A fixed list of static extensions is cached, including CSS, JS, common image and font formats, PDF and MP4. HTML and JSON are not cached by default.
- HLS isn't on the list. Playlists (.m3u8) and segments (.ts or .m4s) aren't default extensions, so without a cache rule every segment request goes to your origin.
- Origin headers are respected. Responses marked private or no-store, and responses carrying a Set-Cookie header, are not cached by default, and only GET requests are cached.
- Default lifetimes fill the gaps. A cacheable 200, 206 or 301 response without Cache-Control or Expires is kept for 120 minutes, a 302 or 303 for 20 minutes, and a 404 or 410 for 3 minutes.
- There is a size ceiling. Files up to 512 MB are cacheable on the Free, Pro and Business plans; the Enterprise default is 5 GB.
Video also needs a contract check. Cloudflare's service-specific terms say that, unless you are an Enterprise customer, serving video through the CDN requires one of its paid services built for it, such as Stream, and that it may limit accounts serving video or a disproportionate share of large files without one. Read the current terms before sending lecture video through a self-serve plan.
Cache rules for HTML and APIs
Cache Rules change what is eligible for caching and for how long (Free plans get 10 rules, Pro 25, Business 50 and Enterprise 300). A sensible set for a learning platform, in the order you'd place them:
| Order | Matches | Setting |
|---|---|---|
| 1. HLS video | File extension is m3u8, ts or m4s | Eligible for cache; use the origin's Cache-Control |
| 2. Public pages | Paths such as /courses/ and /blog/ | Eligible for cache; edge TTL of a few minutes; browser TTL follows the origin |
| 3. Public JSON | Paths such as /api/public/ | Eligible for cache; short edge TTL |
| 4. Private areas | /account/, /checkout/, /admin/ | Bypass cache |
| 5. Logged-in visitors | A session cookie is present | Bypass cache |
An expression for rule 5 might look like this, using Django's default session cookie name; substitute your framework's:
http.cookie contains "sessionid"
Three details make or break these rules:
- Order. Cloudflare's cache rules stack, and when matching rules conflict, the last one wins. That is why the bypass rules go at the bottom. Put a broad "cache /courses/" rule below them and it will cache logged-in pages.
- Cookies on public pages. With "Eligible for cache" and the origin's own headers, a response that sets a cookie isn't cached. With "Ignore cache-control header and use this TTL", Cloudflare strips the Set-Cookie header and caches the page anyway. If that page renders a Django form, every visitor gets the same embedded CSRF token without the matching cookie, and the form fails. Keep cookie-setting forms off pages you cache at the edge.
- Personal bits in "public" HTML. Cloudflare's own guidance warns that caching all HTML can serve visitors content not meant for them. A header that shows a student's name, a cart count or "Continue watching" must come from a bypassed page or a private API call.
For the HLS rule, your origin sets the lifetimes: long for segments, a few seconds for live playlists.
Measuring cache hit ratio
Cache hit ratio is hits divided by all cacheable requests. Track it two ways: by requests, which tells you how often the origin is spared, and by bytes, which tells you how much origin bandwidth you save. Video segments dominate bytes; HTML and API calls dominate requests.
What your origin feels is the miss ratio, and it moves faster than the hit ratio suggests. Take an illustrative 1,00,000 requests a minute at the edge:
| Hit ratio | Requests reaching the origin each minute |
|---|---|
| 90% | 10,000 |
| 95% | 5,000 |
| 99% | 1,000 |
Moving from 95% to 99% looks like a four-point gain, but it cuts origin traffic by a factor of five.
On Cloudflare, check a single URL with the CF-Cache-Status response header. HIT and MISS mean what they say; EXPIRED means the stored copy had expired and a new one came from the origin; REVALIDATED means the origin confirmed the expired copy was still current; UPDATING means a stale copy was served while Cloudflare refreshed it in the background; BYPASS means the request was eligible but the origin's response wasn't cacheable; DYNAMIC means the request wasn't eligible at all, such as HTML with no rule.
curl -sI https://example.com/courses/ | grep -i cf-cache-status
For the whole site, Cache Analytics (Pro plans and above) breaks traffic down by status, path and content type. One quirk: revalidated requests count as served by the origin in the Requests view but as served by Cloudflare in the Data Transfer view, because the body came from cache. The usual culprits behind a low ratio are query-string variants and tokens in the key, short TTLs on files that rarely change, Set-Cookie headers on static responses, and a long tail of rarely requested files, which tiered caching helps with.
Purging without a stampede
Purging removes objects from the cache before they expire. Cloudflare offers purge by single URL, cache tag, hostname, prefix or everything on all plans, with rate limits that vary by plan. A Free account, for example, gets five tag, prefix, hostname or purge-everything requests a minute. A successful purge call only means the request was accepted, so confirm it by checking that CF-Cache-Status is no longer HIT.
The bigger danger is the purge itself. "Purge everything" at 6:55 p.m., just before a live class, empties every edge at once. The next wave of requests misses everywhere and lands on your origin together, a classic cache stampede. To avoid one:
- Don't purge what you can version. Fingerprinted CSS, JS and uploaded files get new URLs, so there is nothing to purge.
- Purge narrowly. Use a tag or prefix, such as all pages of one course, instead of everything.
- Keep tiered caching on, so after a purge only the upper tiers fetch from your origin, and request collapsing merges the rest.
- Prefer expiry to purging for scheduled changes. A short TTL with stale-while-revalidate lets Cloudflare keep serving the old copy (status UPDATING) while it fetches the new one, instead of sending everyone to the origin.
- Purge off-peak, then warm the cache. Request your most important URLs yourself right after a purge, before students do; with tiered caching on, that refills the upper tier every edge draws from.
- Protect the origin with its own cache. With a reverse-proxy cache or Redis behind the CDN, a purge wave costs cache reads, not database queries.
A single CDN is also a single point of failure on exam days; multi-CDN failover covers running two. For how the CDN fits the rest of a video stack, see scaling a video learning platform.
If you run a coaching institute and would rather teach than build a platform, Upclass offers a ready-to-use LMS for coaching institutes, with your own branded app.
Key takeaways
- An edge cache looks up a cache key, serves fresh copies and fetches from the origin only on a miss; request collapsing and tiered caching shrink what the origin sees.
- Keep query-string noise and per-student tokens out of the cache key, or the hit ratio falls apart.
- Cloudflare doesn't cache HTML, JSON or HLS files by default, and its self-serve terms restrict serving video through the CDN.
- Place bypass rules last, because the last matching cache rule wins, and keep cookie-setting forms off edge-cached pages.
- Watch the miss ratio, not just the hit ratio, and purge narrowly or version URLs instead of purging everything.
Frequently asked questions
How does CDN caching work?
The CDN places servers in many cities and routes each user to a nearby one. That edge server checks whether it holds a fresh copy of the requested URL, identified by a cache key. If it does, it answers immediately; if not, it fetches the file from your origin, stores it according to your Cache-Control headers and CDN rules, and serves it. Later requests in that region are then answered from the edge.
What is CDN edge caching?
Edge caching means storing content on the CDN servers at the network's edge, the ones closest to users, rather than only at your origin. For a coaching platform that typically means static files, video segments and public pages. Each edge location keeps its own copies, so the first request in a region may miss while later ones hit. Tiered caching adds a middle layer that edges check before your origin.
What is purge CDN cache?
Purging tells the CDN to delete cached copies before they expire, so the next request fetches a fresh version from your origin. You can usually purge a single URL, everything under a prefix, everything with a cache tag, a whole hostname, or the entire cache. Purge narrowly and avoid peak hours, because a large purge sends a wave of simultaneous misses to your origin.
Is CDN a reverse proxy?
Mostly, yes. A pull CDN such as Cloudflare in proxied mode sits between users and your origin, receives every request, answers what it can from cache and forwards the rest, which is what a reverse proxy does. The difference is scale and purpose: a CDN runs that proxy in many locations and adds caching, TLS termination and attack absorption, while a reverse proxy like Nginx usually sits beside your application servers.