Networking
Content Delivery Network (CDN)
300+ edge locations globally — fetch once, serve from the closest PoP, drop latency from 200ms to 10ms
A content delivery network (CDN) is a globally distributed network of edge servers (Points of Presence, PoPs) that cache and serve static or dynamic content close to end users. A request from a user in Tokyo for a US-origin asset is routed via DNS or anycast to the nearest PoP — typically <50 ms RTT — instead of the origin's 150-250 ms transcontinental link. Major providers: Cloudflare (300+ PoPs, 2026), Akamai (350+ PoPs, the founder, MIT 1998), Fastly, AWS CloudFront. CDNs handle ~25-30% of all global Internet traffic. Beyond static caching, modern CDNs offer edge compute (Cloudflare Workers, Lambda@Edge), DDoS mitigation, image transformation, and TLS termination.
- Major Cloudflare PoPs300+ (2026)
- Akamai PoPs350+
- Origin RTT vs edgetypically 200ms → 10-30ms
- FoundedAkamai 1998 (MIT)
- Static + dynamiccache static, accelerate dynamic
- Edge computeWorkers, Lambda@Edge
Interactive visualization
Press play, or step through manually. The visualization is yours to drive — try it before reading on.
Watch the 60-second explainer
A condensed visual walkthrough — narrated, captioned, under a minute.
How a CDN actually serves a request
You browse a news site in Berlin. The site's origin is a single web server in Virginia, USA — a 90 ms RTT away on a good day. Without a CDN, every image, every script, every CSS file makes that 90 ms round trip; a page with 80 sub-resources spends seconds just on TCP+TLS setup before the first byte arrives.
With a CDN in front, here is what happens instead:
- DNS resolution. Your resolver asks for
cdn.example.com. The CDN's authoritative DNS server reads your resolver's IP (or EDNS Client Subnet) and returns an IP that maps to a Berlin or Frankfurt PoP — RTT ~10 ms. - TCP + TLS handshake. Three packets to set up TCP, one or two RTTs for TLS 1.3. Total: ~30 ms instead of ~270 ms to Virginia.
- Cache lookup. The PoP hashes the request URL, finds the asset in its local SSD cache (or a peer in the same PoP), and returns 200 OK with the body — typically 1-3 ms inside the PoP.
- Cache miss path. If the asset is not in the local PoP, the PoP fetches from a regional shield cache (a single intermediate cache covering many edge PoPs) or from the origin. Cloudflare calls this Argo Tiered Cache; Fastly calls it Origin Shield; Akamai calls it Tiered Distribution. Tiered caching cuts origin requests by 70-90% versus a flat edge-to-origin model.
- Origin offload. Even on a cache miss, the CDN keeps a persistent HTTP/2 or HTTP/3 connection to origin, deduplicates concurrent requests for the same asset (request coalescing), and respects the origin's Cache-Control headers.
Cache keys and what makes a hit
The cache key is what the CDN hashes to decide "is this request the same as a previous one." By default it is the host + URL path + query string. Configurable to ignore query strings (common for static assets where ?v=42 is a cache buster), or to include specific cookies / headers (for personalized variants like Vary: Accept-Language).
| Cache-Control directive | Effect at edge | Effect at browser |
|---|---|---|
public, max-age=31536000 | Cache 1 year | Cache 1 year |
public, s-maxage=86400, max-age=60 | Cache 24 h at edge | Cache 60 s in browser |
private, max-age=300 | Bypass edge cache | Cache 5 min |
no-cache | Re-validate every request | Re-validate every request |
no-store | Never cache | Never cache |
stale-while-revalidate=60 | Serve stale while refreshing | Same |
Cache invalidation strategies
"There are only two hard things in computer science: cache invalidation and naming things." CDNs are a giant case study in both.
- Versioned URLs. Hash the file content, append to the URL:
/main.a1b2c3.js. Old version stays cached forever; new version has a different URL. Used by every modern build tool (webpack, Vite, esbuild). No purge needed. - Purge by URL. Explicit API call: "delete /image.png from every PoP." Cloudflare propagates in <30 seconds globally; Fastly claims median <150 ms via their soft-purge log.
- Purge by tag. Origin sets
Cache-Tag: blog,post-42on responses. A single API callpurge_tag(post-42)invalidates every cached resource carrying that tag — convenient for "edit one blog post, invalidate that post and its index pages" without enumerating URLs. - Soft purge (stale revalidation). Mark cache entry as stale, serve it once more while fetching a fresh copy in the background. Avoids thundering herd against origin after a purge.
Anycast routing vs DNS-based steering
| Mechanism | Granularity | Failover | Used by |
|---|---|---|---|
| DNS steering | Per-client (via resolver IP / EDNS-CS) | Slow (TTL bound) | Akamai (classic), AWS CloudFront |
| Anycast (BGP) | Per-network (BGP-table granularity) | Fast (BGP withdrawal) | Cloudflare, Fastly, Google Cloud CDN |
| Hybrid | Both — DNS picks region, anycast picks PoP | Fast and fine | Modern Akamai, Fastly Magic |
Where the latency actually goes
| Stage | No CDN | With CDN, hot cache | With CDN, cold cache |
|---|---|---|---|
| DNS | 30 ms | 10 ms (anycast) | 10 ms |
| TCP handshake | 90 ms (1 RTT) | 10 ms | 10 ms |
| TLS handshake | 180 ms (2 RTT) | 20 ms (1 RTT TLS 1.3) | 20 ms |
| First byte | 90 ms (1 RTT) | 1 ms (cache hit) | 200+ ms (origin fetch) |
| Total to TTFB | ~390 ms | ~41 ms | ~240 ms |
Real-world Cloudflare data shows median TTFB of 25-50 ms for cache hits and 100-250 ms for cache misses, depending on origin location.
Edge compute platforms
| Platform | Runtime | Cold start | CPU limit | Use case |
|---|---|---|---|---|
| Cloudflare Workers | V8 isolates (JS, Wasm, Rust) | ~5 ms | 50 ms / 30 s paid | API gateways, A/B tests, image rewrites |
| Lambda@Edge | Node, Python (full Lambda) | ~50 ms | 5 s viewer / 30 s origin | Auth, header rewriting, redirect logic |
| CloudFront Functions | JS subset, sandbox | <1 ms | 1 ms | URL rewrites, header manipulation only |
| Fastly Compute | WebAssembly (Rust, Go, JS) | ~50 µs | 50 ms / 60 s | Personalized HTML, edge logic |
| Vercel Edge Functions | V8 isolates, Web standard | ~10 ms | 30 s | SSR, A/B, geo redirects |
DDoS mitigation at the edge
A 1 Tbps DDoS against a single origin server collapses any link short of a backbone. Behind a CDN, the same attack is distributed across hundreds of anycast PoPs:
- Volumetric absorption. 300 PoPs × 4 Tbps each = ~1.2 Pbps of distributed capacity. Cloudflare publicly claims 248 Tbps usable mitigation, AWS Shield Advanced backs CloudFront with similar numbers.
- Application-layer filters. Layer-7 attacks (HTTP floods, slow loris, JS-rendered bots) are filtered by JA3 TLS fingerprints, behavioral models (Bot Management), and rate-limiters running per-PoP.
- Network-layer scrubbing. Magic Transit / AWS Shield Advanced wraps the customer's whole IP space behind the CDN's anycast announcement. Attack traffic dies at the edge; clean traffic GRE-tunnels to the origin.
- Always-on vs on-demand. Always-on routes everything through the CDN regardless of attack state; on-demand swings BGP only during an active attack and cuts over within minutes.
Origin design still matters
A CDN amplifies a good origin and cannot fix a bad one. Watch out for:
- No-cache headers. If origin sends
Cache-Control: no-store, every request reaches origin. CDN gives only TLS termination and DDoS — no caching value. - High Vary cardinality.
Vary: User-Agentcreates a separate cache entry per browser version. Cloudflare ignores Vary on User-Agent by default; respect cardinality manually. - Per-user dynamic responses. Personalized HTML cannot be cached at the edge. Use ESI (Edge Side Includes) or edge-rendered components to cache the wrapper and personalize a fragment.
- Origin without HTTP/2 or HTTP/3. CDN-to-origin still benefits from multiplexing; turn on HTTP/2 on origin even if it's behind the CDN.
- Cookie-keyed cache. Sending session cookies on static assets makes the CDN treat each session as a separate entry. Strip cookies for static paths.
Inspecting CDN behavior
# Which PoP is serving you?
curl -sI https://example.com/asset.js | grep -i 'cf-ray\|x-served-by\|x-cache\|x-amz-cf-pop'
# CF-Ray: 8a1b2c3d4e5f6789-FRA
# X-Cache: HIT, X-Served-By: cache-fra-eddf8230055-FRA
# X-Amz-Cf-Pop: NRT57-P3
# Cache HIT vs MISS
curl -sI https://example.com/asset.js | grep -i 'x-cache\|cf-cache-status\|age'
# Force a cache miss to see origin headers
curl -sI -H 'Cache-Control: no-cache' https://example.com/asset.js
# Trace which anycast PoP is closest
mtr -wbz cdn-cgi.example.com
# Cloudflare API: purge a single URL
curl -X POST 'https://api.cloudflare.com/client/v4/zones/$ZONE/purge_cache' \
-H "Authorization: Bearer $TOKEN" \
-d '{"files":["https://example.com/image.png"]}'
Why CDN matters
- Page load latency. 200-300 ms faster TTFB for distant users; perceived speed dominates conversion rates.
- Traffic spikes. Black Friday or HN-frontpage traffic gets absorbed at the edge — origin sees a flat line.
- DDoS mitigation. Distributed attack capacity built in.
- Origin offload. A 90% edge cache hit rate cuts origin bandwidth and CPU by 10×.
- GDPR / data locality. EU PoPs serve EU users; data never crosses regions if configured.
- TLS termination + WAF. Centralized cert management, OWASP rule enforcement at every PoP.
- Image / video transformation. Cloudflare Polish, Fastly Image Optimizer, Akamai Image Manager resize and re-encode on the fly.
Common misconceptions
- "Only static assets." Modern CDNs handle dynamic via DSA (Dynamic Site Acceleration) — keepalive to origin, TCP optimizations, route selection — and even cache personalized content via ESI fragments and edge compute.
- "A CDN always makes you faster." Cold cache plus origin trip plus CDN-to-origin hop can be slower than direct origin for users physically close to origin. Measure with and without before committing.
- "Free tier fixes everything." A bad origin (slow DB, no caching headers, single region) defeats CDN. Origin design still matters.
- "CDN is just a cache." Modern CDN bundles include TLS, DDoS, WAF, edge compute, image rewrites, video streaming, bot management, analytics, real-time logs — caching is one feature among many.
- "All PoPs cache everything." Edge cache is finite SSD; LRU evicts. Hot assets stay; long-tail content evicts within minutes. Tiered caches help but don't eliminate this.
- "Cache hit rate of 99% is great." Depends on traffic mix. A 99% hit rate that misses on the 1% most expensive responses (large videos, dynamic search) can still saturate origin.
- "CDNs see your private data." Unless you terminate TLS at the edge, the CDN passes encrypted bytes through. With TLS termination, the CDN does see plaintext — choose providers and contracts accordingly.
Frequently asked questions
How does a CDN route users to the nearest PoP?
Two mechanisms. First, DNS-based steering: when a client resolves cdn.example.com, the CDN's authoritative DNS server checks the client's resolver IP (or EDNS Client Subnet hint), looks up the geographic and network proximity, and returns an IP for a nearby PoP. Akamai pioneered this in 1998. Second, anycast: many modern CDNs (Cloudflare, Fastly) announce the same IP from every PoP and let BGP hand the packet to the topologically closest. Anycast is simpler operationally; DNS gives finer per-client control.
What is anycast routing in CDN context?
Anycast is a routing technique where multiple servers announce the same IP prefix via BGP from different geographic locations. The Internet's routing layer naturally delivers each user's packets to the topologically closest instance. CDNs use anycast at the edge so cdn.example.com points at one IP that resolves to the nearest PoP without needing per-client DNS logic. Trade-off: routing changes can move packets between PoPs mid-connection, so TCP/TLS state has to be replicated or accepted as needing reconnection.
Why is TLS termination at the edge a CDN feature?
TLS handshake takes 1-2 RTTs. If the user is in Tokyo and origin is in Virginia, that's ~300 ms RTT × 2 = 600 ms just to set up TLS. Terminating TLS at a Tokyo PoP cuts that to ~10 ms RTT. The PoP holds the certificate, completes the TLS handshake locally, and uses an already-warm connection to origin (or just serves from cache). Cloudflare claims this cuts page-load latency for distant users by 60-70%.
How does cache invalidation work (purge by URL/tag)?
Three common APIs. Purge by URL — explicitly remove /image.png from every PoP. Purge by tag — when origin sets header Cache-Tag: products, calling purge_tag("products") clears every cached object tagged products at every PoP, useful for atomic invalidation of related assets. Purge everything — nuclear option, full cache flush. Cloudflare's purge-by-tag completes in <30 seconds globally; Fastly claims <150 ms median for tag purges, leveraging their VCL+CRDT-based invalidation log.
What is edge compute and how does it differ from origin?
Edge compute runs your code at the CDN PoP instead of the origin. Cloudflare Workers (V8 isolates, ~5 ms cold start), Lambda@Edge (CloudFront, ~50 ms cold), Fastly Compute (Wasm, ~50 µs cold). Use cases: A/B test rewrites, bot blocking, geographic personalization, JWT validation, signed URLs. The function gets the request, optionally reaches origin, optionally caches, returns response — all without an origin round-trip on cache hits. Trade-off: limited runtime (no filesystem, capped CPU/memory) and cold-start variance across PoPs.
How do CDNs mitigate DDoS attacks?
Three layers. (1) Anycast absorbs volumetric attacks — a 1 Tbps attack against a single IP gets dispersed across hundreds of PoPs, none of which sees more than its slice of the traffic. (2) Filtering at the edge — JA3 fingerprints, rate-limiting per IP, regex on payloads, CAPTCHA challenges, all run at the PoP before the request reaches origin. (3) Magic Transit / Shield — entire BGP-anycasted tunnel that wraps an enterprise's whole network behind the CDN's scrubbing capacity. Cloudflare claims 248+ Tbps of mitigation capacity across its PoPs; AWS Shield Advanced sits behind CloudFront.
What is the difference between push and pull CDNs?
A pull CDN fetches each asset from origin on first request, caches it, and serves subsequent requests from cache — the dominant model used by Cloudflare, CloudFront, Fastly. Simpler operationally; cold cache on first request. A push CDN requires the publisher to upload assets directly to the CDN's storage layer, which then replicates to every edge — used for large video libraries (Akamai NetStorage) or static-only sites. Push is faster on first request and cheaper at high cache-miss ratios; pull is more flexible.