CDN Architecture
A CDN cuts latency by turning one origin into hundreds of geographically-spread cache tiers, then using the network's own routing layer (BGP anycast or DNS steering) to pin each user to the closest healthy tier so most bytes travel a few milliseconds instead of crossing an ocean. Everything else — PoPs, TTLs, topologies — exists to serve that one mechanism: keep a fresh-enough copy near the user and answer without touching the origin.
The pieces are easy to list and hard to reason about in isolation. So instead of cataloguing them, this page traces one real request through a real architecture and shows where each piece does its job.
The layout: PoPs, edge tier, and a regional shield
A Point of Presence (PoP) is a rack of edge servers in a metro (say, Mumbai) that terminates TLS and serves cached bytes. A modern CDN does not wire every edge straight to the origin — that is the naive flat topology. Instead it inserts a regional shield (a parent/mid-tier cache), giving a three-level hierarchy: edge → shield → origin. The user only ever talks to the edge; the shield exists purely to absorb edge misses so the origin sees a trickle, not a flood.
Below, follow one 800 KB image request from a user in Pune. The origin is in us-east-1 (Virginia).
Worked trace: one image, cold then warm
URL: https://cdn.example.com/hero.jpg (800 KB). Origin sends Cache-Control: public, max-age=86400 (TTL 24h). First request from Pune, cache cold everywhere:
| Step | Where | Action | Cache state | Added latency |
|---|---|---|---|---|
| 1 | Resolver | Resolve cdn.example.com; anycast/GSLB returns the Mumbai edge IP | — | ~5 ms (NS cached) |
| 2 | User → Edge | TCP + TLS 1.3 (1-RTT) to Mumbai edge | — | ~12 ms |
| 3 | Edge | Cache key hero.jpg lookup | MISS | ~1 ms |
| 4 | Edge → Shield | Fetch from regional parent (same metro) | MISS | ~4 ms RTT |
| 5 | Shield → Origin | Fetch 800 KB from Virginia; read max-age | fill | ~210 ms RTT + transfer |
| 6 | Return | Origin → shield → edge → user; shield & edge both cache | fill both tiers | — |
Cold total ≈ 480 ms, almost all of it the single origin round-trip. Now the second Pune user, 2 minutes later:
| Step | Action | Cache state | Latency |
|---|---|---|---|
| 1 | Resolve (still cached) + reuse warm TLS session | — | ~13 ms |
| 2 | Edge serves hero.jpg from RAM/SSD | HIT | ~3 ms + transfer |
Warm total ≈ 25 ms — a 19× win, and the origin was never touched. The whole point of the architecture is to make step 5 rare.
Why the shield tier matters (the numbers)
Say hero.jpg is requested 50,000 times/day across 12 PoPs in 3 regions, TTL 24h. Count origin fetches:
- Flat topology (every edge → origin): each PoP misses once per TTL → 12 origin fetches/day. Worse, when the TTL expires all 12 edges refetch near-simultaneously — a cache stampede hammering the origin.
- Hierarchical + shield (edges → 1 shield/region → origin): the 4 edges in a region share their shield, so only the shield touches the origin → 3 origin fetches/day, one per region.
- With request coalescing at the shield: concurrent misses for the same key collapse into a single upstream fetch, so even a spike inside one region stays at 1 fetch.
That is a 4× origin-offload improvement from one tier, and the improvement grows with the number of PoPs. The cost: every miss now pays one extra intra-region hop (step 4 above, ~4 ms), and the shield is a new hot-spot to capacity-plan and keep healthy.
Getting the user to the right PoP: two routing mechanisms
Steps 1–2 of the trace hid the hardest decision: which edge IP does the user get? There are two dominant answers, and they trade off differently.
Anycast (BGP): every PoP announces the same IP (e.g. 203.0.113.10) via BGP. The internet's routing fabric delivers the packet to whichever PoP is closest in BGP terms. No per-request logic — the network is the load balancer. This is the Cloudflare model.
DNS / GSLB steering: each PoP has a distinct IP. The CDN's authoritative DNS looks at the resolver's location (via EDNS Client Subnet), current PoP load and health, then returns the best IP. This is the classic Akamai model.
Freshness: TTL, headers, and why invalidation is not a correctness tool
The origin controls caching through response headers; the CDN obeys them. The ones that matter:
Cache-Control: max-age=86400— cache for 24h before revalidating. This is the primary knob.s-maxage— a separate TTL that only shared caches (the CDN) obey, overridingmax-agethere; browsers ignore it and keep usingmax-age. Typical pattern: longs-maxagefor the CDN you can purge, shortmax-agefor browsers you cannot.ETag/Last-Modified— on expiry the edge sends a conditionalIf-None-Match; origin replies304 Not Modified(no body) if unchanged, so revalidation is cheap.stale-while-revalidate=60— serve the stale copy instantly while refetching in the background. This is the cleanest stampede defence.Vary: Accept-Encoding— splits the cache key. Every value inVarymultiplies your object count;Vary: Cookieor caching the full query string can collapse your hit ratio to near zero.
Invalidation (purge) removes an object before its TTL expires — used when content changes. But a purge propagates to every PoP eventually (seconds, sometimes longer), so it is not instantaneous and must never be relied on for correctness. The correct pattern for must-be-fresh assets is versioned URLs (hero.v7.jpg or ?v=7): a new URL is a guaranteed cache miss, no purge required.
Pitfalls
- Cache stampede on TTL expiry. The moment a hot object expires, every concurrent request at a PoP misses and stampedes upstream. Defend with
stale-while-revalidate, request coalescing, and a shield tier — not by hoping. - Cache-key fragmentation. Caching on
Vary: Cookie, tracking query params, or per-user headers means near-100% miss rate — you built a very expensive proxy. Normalize the key: strip tracking params, only vary on what actually changes the bytes. - Purge treated as instant. Teams ship a hotfix, purge, and assume every user sees it immediately. Propagation is eventual; use versioned URLs when correctness depends on it.
- DNS TTL vs failover. A long DNS TTL means clients keep hitting a dead PoP after you've steered away (stale cached record); too short floods your DNS and resolvers ignore it anyway. Anycast sidesteps this but trades away load-aware steering.
- EDNS Client Subnet not honored. Public resolvers that don't forward the client subnet map the user to the resolver's location — a user on
8.8.8.8can get routed to a distant PoP near a Google datacenter. - Negative caching. Caching a
500or404with a long TTL poisons the edge and serves the error long after the origin recovers. Set short TTLs (or none) for error responses. - Anycast + long-lived connections. A BGP reconvergence mid-stream can shift packets to a different PoP that has no TCP state, resetting the connection — a real concern for large downloads and WebSockets.
When to use which architecture
Routing: anycast vs DNS/GSLB
Signals that point to anycast: you serve mostly static assets, you want operational simplicity and instant failover, and DDoS resilience matters (attack traffic spreads across all PoPs automatically). What you gain: robustness and no DNS-TTL failover lag. What it costs: BGP chooses shortest AS-path, not lowest latency, and you get little per-request or load-aware control.
Signals that point to DNS/GSLB: you need load-aware balancing, geo-precise steering, or the ability to drain a PoP for maintenance without dropping traffic. What you gain: fine-grained, per-client control. What it costs: DNS-TTL failover lag, dependence on EDNS Client Subnet for accuracy, and more infrastructure to operate.
Choose anycast when delivery is static and you value simplicity and DDoS resilience; prefer DNS/GSLB when you must steer on live load/health or gracefully drain PoPs. Large CDNs run both: anycast to reach a region, then intra-region logic to pick a machine.
Topology: flat vs hierarchical (shield) vs mesh
Choose flat only for a small footprint (a handful of PoPs) where the extra hop isn't worth it and origin load is trivially small. Choose hierarchical + shield — the default for anything at scale — when you have many PoPs and want to protect the origin: you trade one intra-region hop (~a few ms on misses) and a new tier to operate for a large origin-offload win and stampede control. Reach for mesh (peers fill from each other) only for enormous catalogs where even shields can't hold the working set and peer-fill beats going to origin — accepting real complexity in consistency and loop-avoidance. Most production CDNs are a hybrid: hierarchical for static, with mesh or dynamic acceleration paths for uncacheable content.
Takeaways
- The whole architecture serves one goal: answer from a cache near the user and touch the origin as rarely as possible — the trace showed 480 ms cold vs 25 ms warm.
- A shield tier turns N per-PoP origin misses into ~1 per region and tames stampedes; the price is one extra hop and a tier to run.
- Anycast trades steering control for robustness and instant failover; DNS/GSLB trades operational complexity for load- and geo-aware precision. Big CDNs use both.
- Freshness is TTL + headers; purge is eventual, so use versioned URLs when correctness depends on the update landing everywhere.
Re-authored and deepened for this guide. Sources: Cloudflare Learning Center (“What is a CDN / How CDNs work / Anycast”); Akamai and Fastly documentation on cache hierarchies, shielding, and request collapsing; MDN Web Docs on HTTP caching (Cache-Control, ETag, Vary, stale-while-revalidate, RFC 9111); and Grokking the System Design Interview (CDN chapter). Latency figures are representative order-of-magnitude values for a Pune–Mumbai–Virginia path, not measurements.
🤖 Don't fully get this? Learn it with Claude
Stuck on CDN Architecture? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **CDN Architecture** (System Design) and want to truly understand it. Explain CDN Architecture from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **CDN Architecture** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **CDN Architecture** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **CDN Architecture** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.