Concept 5: Content Delivery Networks (CDNs)
System Design Bible — File 05 of 10 Difficulty: ★★★☆☆ Prerequisites: Files 01–02, plus the physics and DNS/HTTP-caching facts in Section 0.
Table of Contents#
- Prerequisites — What You Must Understand First
- 0.1 Latency has a hard floor set by the speed of light
- 0.2 A proxy, and "origin" vs "edge"
- 0.3 DNS as a routing tool, not just a phone book
- 0.4 Counting the round trips — the number a CDN actually attacks
- 0.5 Bandwidth, latency and throughput are three different things
- 0.6 TCP slow start and the congestion window — why long RTT throttles transfer
- 0.7 Autonomous Systems, BGP, peering and transit — how the internet routes
- 0.8 Anycast from first principles
- Architectural Definition & "The Why"
- The Recursive Sub-Concept Tree
- 2.1 Origin Server · 2.2 Edge Server / PoP · 2.3 Push vs Pull · 2.4 Hit ratio & cache hierarchy · 2.5 TTL &
Cache-Control· 2.6 Anycast - 2.7 The Cache Key · 2.8 Query strings · 2.9 Cookies · 2.10
Varyat the edge · 2.11 Request collapsing · 2.12 Cache-status headers &Age· 2.13 Surrogate keys · 2.14 IXPs, peering and embedded caches · 2.15 The private backbone
- 2.1 Origin Server · 2.2 Edge Server / PoP · 2.3 Push vs Pull · 2.4 Hit ratio & cache hierarchy · 2.5 TTL &
- Deep-Dive Mechanics: How a CDN Serves a Request
- Anycast & Request Routing — How Users Find the Nearest Edge
- Cache Control, Invalidation & Dynamic Content
- Edge Protocol Optimizations — TLS, HTTP/2, QUIC, Compression
- Dynamic Content Acceleration — Why a CDN Helps Even When Nothing Is Cacheable
- Video & Large-File Delivery
- Edge Compute
- Security at the Edge
- Measuring a CDN
- Pros, Cons & Trade-offs
- Interview Diagnostic Framework (Symptom → Solution)
- Real Implementations & Product Landscape
- Real-World Engineering Scenarios
- Interview Gotchas & Failure Modes
- Whiteboard Cheat Sheet
0Prerequisites — What You Must Understand First#
A CDN is "caching (File 02) + geography." The "geography" part rests on one piece of physics and one piece of internet plumbing.
This section is long, and deliberately so. Almost every wrong answer about CDNs in an interview traces back to a missing prerequisite: the candidate does not actually know how many round trips a page load costs, does not know why a fat pipe with a long delay still transfers slowly, does not know what DNS does between "user types a name" and "browser opens a socket," and does not know what BGP is even though anycast — the thing they are about to name-drop — is made of BGP. We will fix all of that before the word "CDN" does any real work.
0.1Latency has a hard floor set by the speed of light#
You cannot make distant things fast, and understanding why is the entire justification for CDNs. Data travels through fiber-optic cable at roughly two-thirds the speed of light — fast, but finite. A signal from Sydney to a server in Virginia crosses ~16,000 km each way; even at light-ish speed, the round trip takes ~160–200 milliseconds, and no faster CPU, bigger server, or better code can reduce it — it's bounded by distance and physics. Worse, loading a web page isn't one round trip: it's a DNS lookup, then a TCP handshake, then a TLS handshake, then the HTML, then dozens of follow-up fetches for CSS/JS/images — each potentially its own round trip. Stack dozens of 200 ms round trips and you get seconds of load time for a faraway user, while a nearby user gets the same page in a fraction of a second. The inescapable conclusion: the only way to cut distance-latency is to cut the distance — physically place a copy of the content near the user. That is what a CDN does, and it's why "add a faster server" can never substitute for it. Keep this floor in mind: latency between continents is a law of physics, not an engineering shortcoming.
0.1.1 Do the arithmetic yourself — the numbers you should be able to produce on a whiteboard#
Assertions are not understanding. Derive the floor from constants, because an interviewer will ask "how do you know Tokyo can't be fast from Virginia?" and the answer is four lines of arithmetic.
**Constant 1 — the speed of light in vacuum, c, is 299,792,458 m/s, which you round to 300,000 km/s**. Nothing carrying information travels faster; this is not an engineering limit that a better vendor beats, it is a property of spacetime.
Constant 2 — light in glass is slower. Optical fibre is made of silica glass with a refractive index of about 1.47. Refractive index n is defined as the ratio of light's speed in vacuum to its speed in that medium, so the propagation speed inside the fibre is c / n = 300,000 / 1.47 ≈ 204,000 km/s. Engineers round this to ~200,000 km/s, or equivalently **"two-thirds of c," or "5 microseconds per kilometre," or "1 millisecond per 200 km."** Memorize the last form; it lets you do these estimates in your head.
Constant 3 — cable does not run in straight lines. The great-circle distance (the shortest path over the surface of the sphere) from New York to London is about 5,585 km. The actual submarine cable route is longer — cables follow ocean-floor topography, avoid trenches and fishing grounds, and land at specific cable stations — so a realistic fibre path is 6,500–7,000 km. A useful rule of thumb: real fibre distance ≈ 1.2–1.5× great-circle distance.
Now the computation, twice: once for the theoretical floor, once for reality.
NEW YORK -> LONDON
(a) Theoretical floor, great-circle distance, speed of light in glass
one way = 5,585 km / 200,000 km/s = 0.0279 s = 27.9 ms
round trip= 2 x 27.9 = 55.8 ms <-- HARD FLOOR
(b) Realistic, actual cable path
one way = 6,800 km / 200,000 km/s = 34.0 ms
round trip= 68.0 ms of pure propagation
plus per-hop equipment delay: ~12 routers x ~0.5 ms = ~6 ms
plus queuing/serialization = ~2-6 ms
OBSERVED RTT = ~70-80 msMeasured reality agrees: ping between a New York datacenter and a London datacenter reliably reports 70–80 ms round-trip time. The floor is 56 ms and you observe 75 ms, so the "overhead" the industry can still optimize is about 19 ms — roughly a quarter of the total. Three-quarters of that latency is the speed of light and cannot be optimized by anyone, ever, for any amount of money.
Sub-Concept: RTT (Round-Trip Time). RTT is the elapsed time from the moment a machine puts the first bit of a message on the wire to the moment it receives the first bit of the reply. It is the single most important number in networked-system design because virtually every protocol is a conversation, and a conversation costs RTTs. It is not the same as "latency" loosely used: one-way latency is half of RTT only when the path is symmetric, which on the internet it frequently is not (traffic to you and traffic from you can take different routes with different lengths, a condition called path asymmetry). You measure RTT with
ping(which sends an ICMP echo request and times the echo reply) or, more usefully for real traffic, withcurl -w '%{time_connect}\n' -o /dev/null -s https://example.com, which reports how long the TCP connection took to establish — one RTT. Why it matters here: every optimization in this entire file is, ultimately, either "reduce the RTT" (move the server closer) or "reduce the number of RTTs" (change the protocol). Those are the only two moves available.
Run the same arithmetic for the other pairs you will be asked about, and commit the table to memory:
| Path | Great-circle | Floor RTT (fibre) | Typical observed RTT |
|---|---|---|---|
| Same city (client → local PoP) | 5–50 km | ~0.5 ms | 1–10 ms (last-mile access dominates) |
| Same metro region | ~100 km | ~1 ms | 5–15 ms |
| New York → Chicago | 1,150 km | ~11.5 ms | 20–25 ms |
| New York → London | 5,585 km | ~56 ms | 70–80 ms |
| London → Singapore | 10,850 km | ~109 ms | 150–180 ms |
| Sydney → Virginia (US) | 15,900 km | ~159 ms | 200–230 ms |
| Anywhere → geostationary satellite → anywhere | 71,600 km (up+down twice) | ~477 ms in vacuum | 600+ ms |
The satellite row is included because it is the cleanest proof that the physics is real: geostationary orbit is 35,786 km up, the signal travels through near-vacuum at full c rather than through glass at 0.68c, and it is still catastrophically slow, purely because the distance is enormous. No compression algorithm, no faster modem, and no better code changes that. (This is precisely why Starlink and other LEO — Low Earth Orbit — constellations exist: by flying at 550 km instead of 35,786 km they cut the propagation distance by 65×, trading a hard latency problem for a hard "you need thousands of satellites and constant handoffs" problem.)
Why "the last mile" is the other half of the story. Notice the first row of the table: a client in the same city as a PoP still typically sees 1–10 ms, far above the 0.5 ms propagation floor. That gap is the last mile — the access network between the user's device and their ISP's first router. Wi-Fi adds 1–3 ms and retransmits on interference; DOCSIS cable modems add 5–15 ms of scheduling delay because upstream transmission slots are granted by the head-end rather than taken freely; 4G LTE adds 30–50 ms of radio-scheduling and control-plane latency; 5G targets 10–20 ms. The practical consequence for CDN design is important and often missed: once the edge is inside the user's metro area, further reductions in distance buy almost nothing, because access-network latency now dominates. This is why CDNs stop at a few hundred to a few thousand PoPs rather than building one per neighbourhood — the returns flatten. It is also the argument for putting caches inside the ISP (§2.14, and Netflix Open Connect in §15.1), which attacks the last mile itself rather than the backbone.
0.1.2 The business case, in real published numbers#
Rule 6 says tie everything to a real limit. The physical limit is above; the economic limit that got CDNs funded is this. Amazon's oft-cited internal experiment found every 100 ms of added latency cost about 1% of sales. Google found that deliberately increasing search-results latency by 400 ms reduced searches per user by 0.6%, and that the effect persisted for weeks after the latency was removed. Akamai's 2017 study found a 100 ms delay reduced conversion rates by 7%, and that 53% of mobile visitors abandon a page taking over 3 seconds. Google's Core Web Vitals — the performance metrics that feed search ranking — set a "good" threshold of 2.5 seconds for Largest Contentful Paint (LCP), the time until the biggest visible element on screen has rendered. If a Sydney user's baseline RTT to your Virginia origin is 220 ms and a page load costs even 8 sequential round trips, you have burned 1.76 seconds before a single byte of image data moves. You cannot hit a 2.5 s LCP budget from the other side of the planet. That is the whole business case in one sentence.
Hold this: latency is 5 µs per kilometre of fibre, ~75 ms New York↔London, ~220 ms Sydney↔Virginia, three-quarters of it unfixable physics; and a few hundred milliseconds is worth a measurable percentage of revenue.
0.2A proxy, and "origin" vs "edge"#
A proxy server is a machine that sits between a client and a destination server, forwarding requests and responses on their behalf. A caching proxy additionally keeps a copy of responses it has seen, so it can answer future identical requests itself without contacting the destination. A CDN is a globally-distributed fleet of caching proxies. Two terms recur constantly: the origin is your authoritative server (or storage bucket) that holds the real, canonical content — the source of truth. An edge server (or PoP, Point of Presence) is one of the CDN's caching proxies, positioned in a data center physically near end users. The whole game is: users talk to the nearby edge (fast); the edge only occasionally talks to the faraway origin (slow, but rare). If "cache hit," "cache miss," and "TTL" from File 02 aren't crisp, re-read File 02 §2 — a CDN is those exact concepts spread across the planet.
Forward proxy vs reverse proxy — the distinction that trips people up. The word "proxy" covers two mirror-image deployments and CDNs are firmly one of them. A forward proxy sits in front of clients and is deployed on behalf of the clients: a corporate web proxy that all employee browsers are configured to use, a VPN egress node, an ad-blocking proxy. The clients know about it (they are configured to use it) and the destination servers do not (they just see traffic from the proxy's IP). A reverse proxy sits in front of servers and is deployed on behalf of the server operator: the clients do not know it exists (they think they are talking to example.com and they are, as far as they can tell), and the real servers behind it are hidden. A CDN edge server is a reverse proxy — you, the site owner, put it there; your users never configured anything; and it impersonates your origin so completely that the browser's address bar, its TLS certificate check, and its cookies all behave as if it were your origin. Everything File 01 taught about reverse proxies — TLS termination, connection pooling, health checks, header rewriting — applies verbatim to a CDN edge, because a CDN edge is a reverse proxy that additionally caches and happens to have 300 siblings around the world.
The exact terms, because they are used loosely and you should not be loose with them:
- Origin server (or just "origin"). The machine or service that holds the canonical, authoritative bytes. It might be an application server running Django or Spring, an object-storage bucket like Amazon S3 (File 09), a load balancer fronting a fleet (File 01), or another CDN. "Authoritative" is the operative word: when the edge and the origin disagree, the origin is right by definition.
- Origin pull / origin fetch. The act of an edge server requesting an object from the origin because it does not have a valid copy. Also called a fill or a cache fill, because the result fills the cache. In CDN dashboards this shows up as "origin requests" or "origin bandwidth" and it is the number you are trying to drive to near zero.
- Edge server. One physical machine in the CDN's fleet running the caching reverse-proxy software.
- PoP (Point of Presence). One location — a rack, a cage, or a whole floor in a datacenter — containing many edge servers plus the switches and routers that connect them to the outside world. When a vendor says "300 PoPs" they mean 300 locations, each of which may hold anywhere from four to four hundred servers.
- Edge (collective). All of the PoPs, considered as one distributed system. "Run it at the edge" means "run it on the PoP fleet rather than at the origin."
- Eyeball network. Industry jargon for a consumer ISP — a network full of end users ("eyeballs") consuming content, as opposed to a content network full of servers producing it. CDNs exist to sit as close to eyeball networks as possible; you will see the term in peering discussions (§2.14).
The economics in one line, which is the entire reason the architecture is shaped this way: the user↔edge hop is short, cheap, and traversed billions of times; the edge↔origin hop is long, expensive, and — if you have done your job — traversed rarely. Every design decision in this file is an attempt to move traffic from the second category into the first.
0.3DNS as a routing tool, not just a phone book#
From File 01 §0.4 you know DNS translates a name (example.com) into an IP address. The extra idea you need for CDNs: **DNS can return different answers to different users.** When a user's device asks "what's the IP for cdn.example.com?", the CDN's DNS can look at where the asker is and reply with the IP of the nearest edge server — so users in Tokyo and users in London, asking the identical question, get different IPs pointing to different nearby PoPs. This "answer depends on who's asking and where they are" is one of the two mechanisms (the other being anycast, covered in §4) that steer each user to their closest edge. So DNS here is not merely a static lookup — it's an active, location-aware routing layer. This reframing is essential before Section 4.
0.3.1 DNS resolution in full — every actor, every record, every cache#
You cannot reason about GeoDNS, TTL-bounded failover, or EDNS Client Subnet until you can narrate a resolution end to end. Here it is with real names and real timings.
The actors.
- The stub resolver. A small library inside your operating system (on Linux,
glibc's resolver orsystemd-resolved; on macOS,mDNSResponder; on Windows, the DNS Client service). It knows almost nothing — it just forwards the question to a configured recursive resolver and caches the answer briefly. Your browser also keeps its own small DNS cache in front of this (Chrome's is visible atchrome://net-internals/#dns), which is why a DNS change sometimes appears to take effect in one application and not another. - The recursive resolver (a.k.a. recursive nameserver, or just "the resolver"). The machine that does the actual work of walking the DNS hierarchy on your behalf. It is usually run by your ISP, or it is a public resolver you chose: **Google Public DNS at
8.8.8.8, Cloudflare at1.1.1.1, Quad9 at9.9.9.9, or OpenDNS at208.67.222.222. It maintains a large cache shared across all of its users. This machine's location, not yours, is what a GeoDNS system sees** — hold that thought, it is the single biggest weakness of DNS-based routing (§4.3). - The root servers. Thirteen logical root nameservers named
a.root-servers.netthroughm.root-servers.net, which are actually over 1,900 physical machines worldwide because each logical server is itself anycast (§0.8). They know one thing: which nameservers are authoritative for each top-level domain (.com,.org,.io,.uk). - The TLD (Top-Level Domain) servers. For
.com, these are Verisign'sa.gtld-servers.netand friends. They know which nameservers are authoritative for each second-level domain under them (example.com). - The authoritative nameserver. The machine that holds the actual, final answer for
example.com— the zone file with all its records. If you use a CDN, this is very often the CDN's own nameserver, because owning the authoritative DNS is how a CDN gets to give different answers to different askers.
The walk, with a stopwatch. Your laptop in Sydney wants www.example.com and nothing is cached anywhere:
stub ---(1)--> recursive resolver (ISP, 10 ms away)
resolver ---(2)--> ROOT server: "who serves .com?" [~20 ms]
<------ "ask a.gtld-servers.net (192.5.6.30)"
resolver ---(3)--> .com TLD server: "who serves example.com?" [~40 ms]
<------ "ask ns1.example-cdn.net (203.0.113.9)"
resolver ---(4)--> authoritative NS: "A record for www.example.com?" [~30 ms]
<------ "www.example.com. 60 IN A 198.51.100.42"
stub <---(5)--- resolver returns 198.51.100.42, and caches it for 60 s
TOTAL COLD RESOLUTION: ~110 ms**That is 110 milliseconds before your browser has even begun to open a TCP connection.** On a warm cache — which is the common case, because the resolver serves thousands of users and someone asked recently — steps 2 through 4 vanish and the whole thing costs one 10 ms round trip to the resolver. The variance between 10 ms and 110 ms for the identical operation is why DNS optimization (short chains, few CNAMEs, prefetching) is a real discipline.
The record types you must know by name.
- **
Arecord — maps a name to a 32-bit IPv4 address**.www.example.com. 60 IN A 198.51.100.42. Read the fields left to right: the name, the TTL in seconds (60), the class (INfor Internet — the only one anyone uses), the type, and the value. - **
AAAArecord ("quad-A") — the same thing for a 128-bit IPv6 address**, e.g.2606:4700:3033::6815:2a. It is called AAAA because an IPv6 address is four times the size of an IPv4 one. A modern client asks for both A and AAAA and uses Happy Eyeballs (RFC 8305) — it races an IPv6 and an IPv4 connection attempt with a small head start for IPv6 and uses whichever completes first, so that a broken IPv6 path costs milliseconds rather than a 30-second timeout. - **
CNAMErecord** (Canonical Name) — an alias: "this name is really that other name; go resolve that instead."www.example.com. 300 IN CNAME example.com.cdn-provider.net.This is the single most important record type for CDN onboarding, because it is how you hand control of a hostname to a CDN without giving them your whole domain: you pointwwwat the CDN's hostname, and now the CDN's authoritative servers decide which IP each user gets. The cost is an extra resolution round trip — the resolver must now resolve the target name too — which is why deep CNAME chains (www→cdn→region→pop) measurably hurt cold-start latency. The rule to remember: a CNAME cannot exist at the zone apex (the bareexample.comwith no subdomain), because the apex must also carrySOAandNSrecords and the DNS spec forbids a CNAME coexisting with any other record. Providers work around this with non-standard "ALIAS" / "ANAME" / "CNAME flattening" records — Route 53's alias record and Cloudflare's CNAME flattening both resolve the target server-side and return the resulting A record, giving you apex-level CDN pointing without violating the protocol. - **
NSrecord** — names the authoritative nameservers for a zone. This is the record the TLD server hands back in step 3. - **
SOArecord (Start of Authority) — zone metadata: the primary nameserver, the admin email, a serial number for zone-transfer versioning, and the negative-caching TTL that controls how long a "this name does not exist" answer (an NXDOMAIN**) may be cached. - **
TXTrecord** — arbitrary text, used in practice for domain-ownership proofs (which is how you validate a TLS certificate with an ACME DNS challenge) and for email authentication (SPF, DKIM, DMARC).
**Sub-Concept: TTL in DNS, and why it is a commitment, not a hint. Every DNS record carries a TTL (Time To Live)** in seconds. It instructs every cache along the path — the recursive resolver, the OS stub, the browser — how long it may reuse this answer without asking again.
A 198.51.100.42with TTL 60 means "you may use this for 60 seconds." The crucial and under-appreciated property: once you have handed out a record with TTL 3600, you have no way to take it back. There is no purge, no invalidation, no callback. Somewhere in the world a resolver will use that answer for the next hour, and a meaningful minority of resolvers and client libraries ignore TTLs entirely and cache for their own convenience (Java's JVM historically cached DNS forever by default via thenetworkaddress.cache.ttlsecurity property; many mobile apps and connection pools resolve once at startup and never again). Consequences you must be able to state: (1) DNS-based failover is bounded below by your TTL and in practice is worse than your TTL; a 60 s TTL means "most users move within 60 s, some within 10 minutes, a few never until they restart." (2) Short TTLs cost you: every expiry forces a fresh resolution, adding a round trip and load on your authoritative servers; a 30 s TTL on a site with 10 million daily users generates a lot of DNS queries, and you pay per query on managed DNS (Route 53 charges roughly $0.40 per million standard queries, and about $0.60–$0.70 per million for latency-based or geolocation routing). (3) The migration playbook is therefore always: **lower the TTL to 60 s a day or two before the change, make the change, wait, then raise the TTL back.** Forgetting the "before" is how you turn a five-minute cutover into a two-hour one.
How to actually look at this. dig www.example.com A +noall +answer prints the answer section with TTLs. dig +trace www.example.com performs the entire root→TLD→authoritative walk in front of you, printing each delegation — run it once and the diagram above stops being abstract. dig @1.1.1.1 www.example.com asks a specific resolver, which is how you compare what different resolvers are being told (and thus observe GeoDNS in action). dig CHAOS TXT id.server @1.1.1.1 asks an anycast server to name itself, revealing which PoP you actually reached.
Hold this: DNS is a hierarchy of caches with commitments called TTLs, CNAMEs are how a CDN takes control of a hostname, the answer depends on which resolver asks, and you can never un-hand-out a record.
0.4Counting the round trips — the number a CDN actually attacks#
Everything above establishes that one round trip is expensive. The reason CDNs are transformative rather than merely nice is that **a web page load is not one round trip — it is a long, mostly sequential chain of them**, and each link in the chain is multiplied by the RTT. Count them explicitly, because this count is the thing a CDN attacks from two directions at once (make RTT smaller, and make the count smaller).
Take a user in Sydney loading https://shop.example.com/ served directly from an origin in Virginia. RTT = 220 ms. Nothing is cached anywhere. Here is the complete ledger:
STEP RTTs ELAPSED (at 220 ms/RTT, DNS to a nearer resolver)
------------------------------------------ ----- ---------------------------------------------
1. DNS: stub -> recursive resolver 1 ~10 ms (resolver is local)
2. DNS: resolver -> root -> TLD -> auth 3 ~110 ms cold (0 ms if warm)
3. TCP handshake: SYN -> SYN/ACK -> ACK 1 +220 ms = 330 ms
4. TLS 1.2 handshake (2 RTTs) 2 +440 ms = 770 ms
(TLS 1.3 needs only 1 RTT -> 1 +220 ms = 550 ms)
5. HTTP GET / -> first byte of HTML 1 +220 ms = 990 ms <-- TTFB
6. HTML parsed; browser discovers CSS + JS
New connection to a second hostname?
-> repeat DNS + TCP + TLS 4-7 +880-1540 ms
7. GET /app.css, GET /app.js 1 +220 ms
8. CSS parsed; discovers webfont + images 1 +220 ms
9. Fonts and hero image fetched 1 +220 ms
------------------------------------------ ----- ---------------------------------------------
TOTAL (single origin, TLS 1.3, warm DNS) ~9-11 RTTs ~2.0-2.4 SECONDS before the page is usableNow change exactly one thing — put a CDN edge in Sydney, 8 ms away — and re-run the same ledger. Steps 3, 4, 5, 7, 8 and 9 all now cost 8 ms instead of 220 ms. The only step that still costs a long trip is the first origin fill for the HTML, and only on a cache miss, and only for the first user:
TOTAL (CDN edge 8 ms away, everything cached) ~9 RTTs x 8 ms ~= 75-120 msTwo-and-a-half seconds becomes a tenth of a second, with not one line of application code changed. That number — roughly a 20× improvement in wall-clock page load for a distant user — is why CDNs are not an optimization you get to defer.
Now notice the second lever. The count itself (9–11) is attackable, and modern edges attack every item on the list:
- DNS round trips are removed by a warm resolver cache, by DNS prefetching (
<link rel="dns-prefetch">tells the browser to resolve a hostname before it is needed), and reduced by not sharding assets across many hostnames (an HTTP/1.1-era optimization that is now actively harmful, §6.2). - The TCP handshake is removed for repeat connections by TCP Fast Open (a kernel feature that lets a client send data in the
SYNpacket using a cryptographic cookie from a prior connection), and made cheap by connection reuse — one connection serving hundreds of requests. - The TLS handshake drops from 2 RTTs to 1 with TLS 1.3, to 0 with session resumption and 0-RTT (§6.1).
- Step 6 — extra hostnames — is removed by connection coalescing in HTTP/2: if two hostnames resolve to the same IP and are covered by the same certificate, the browser reuses the existing connection instead of building a new one.
- Steps 7–9 — discovery chains — are removed by HTTP/2 Server Push (largely deprecated now, for reasons in §6.2) and by
<link rel="preload">and 103 Early Hints, an HTTP status code the edge can emit while the origin is still thinking, telling the browser "you are going to need/app.cssand/hero.jpg, start fetching them now." Early Hints is a genuinely CDN-shaped optimization: the edge can send it instantly from cached knowledge even though the origin response is still 220 ms away.
Hold this: **a page load costs 9–11 sequential round trips; a CDN multiplies every one of them by a 10× smaller RTT and removes several of them outright. The product of those two effects is the whole value proposition.**
0.5Bandwidth, latency and throughput are three different things#
These three words are used interchangeably in casual speech and they mean completely different things. Conflating them produces the single most common wrong intuition in system design: "our users have gigabit fibre, so file size doesn't matter." It matters enormously, and here is why.
Latency is delay — how long one bit takes to get from A to B, measured in milliseconds. It is set by distance and by per-hop processing (§0.1). Think of it as the length of the pipe.
Bandwidth is capacity — how many bits per second the link can carry, measured in Mbps or Gbps. It is set by the physical medium and the equipment. Think of it as the width of the pipe.
Throughput (also called goodput when you count only useful application bytes and exclude protocol headers and retransmissions) is what you actually achieve — the real bits per second your transfer sustains. It is bounded above by bandwidth, but it is very often far below it, and the thing dragging it down is usually latency. Think of it as the water actually flowing.
The analogy that makes this stick: a truck full of hard drives driving from Los Angeles to New York has colossal bandwidth (a truck holds petabytes; divided by 40 hours that is hundreds of Gbps) and appalling latency (40 hours for the first bit). AWS literally sells this — the Snowball and Snowmobile appliances — because for a 100 PB migration, driving is genuinely faster than any network you can afford. Conversely, a stock-trading microwave link between Chicago and New York has pitiful bandwidth (a few hundred Mbps) and superb latency (microwaves travel through air at ~0.99c and take a straighter path than fibre, so ~4 ms one way versus fibre's ~6.5 ms), and firms have spent hundreds of millions of dollars for those 2.5 milliseconds. Bandwidth is bought; latency is bounded by physics.
Sub-Concept: the Bandwidth-Delay Product (BDP) — the number that explains everything. The BDP is
bandwidth × round-trip time, and it has units of bytes. Physically it is the amount of data that is "in flight" on the wire at any instant — data the sender has transmitted but that the receiver has not yet acknowledged. It is the volume of the pipe: length (RTT) × width (bandwidth).Work it: a 100 Mbps link with a 200 ms RTT has
BDP = 100,000,000 bits/s × 0.2 s = 20,000,000 bits = 2.5 MB. To keep that link fully busy, the sender must be allowed to have 2.5 MB of unacknowledged data outstanding at all times. If it may only have 64 KB outstanding, then it sends 64 KB, stops, and waits 200 ms for the acknowledgement — achieving65,536 bytes / 0.2 s = 327 KB/s ≈ 2.6 Mbpson a 100 Mbps link. You are using 2.6% of the bandwidth you paid for, and the cause is entirely the delay.This is not hypothetical: the original TCP receive-window field is 16 bits, capping the advertised window at 65,535 bytes, which is exactly the 64 KB in the calculation above. The fix is TCP Window Scaling (RFC 7323), a TCP option negotiated in the SYN packets that specifies a left-shift factor (0–14) applied to the window field, raising the maximum window to 1 GB. It is on by default on every modern OS (
net.ipv4.tcp_window_scaling = 1on Linux) — but middleboxes, old firewalls, and misconfigured appliances still occasionally strip the option, and the symptom is exactly this: a fast link that inexplicably transfers at a few megabits over long distances. This condition — a high-bandwidth, high-latency path that TCP cannot fill — has a name: a "long fat network," or LFN, pronounced "elephant."The CDN tie-back, which is the punchline of this whole sub-section: shortening the RTT from 200 ms to 10 ms shrinks the BDP from 2.5 MB to 125 KB. Suddenly the window sizes, buffers, and congestion-control behaviour that were catastrophically inadequate for the long path are more than sufficient for the short one. A CDN does not just reduce the delay; it reduces the delay to the point where TCP starts working properly at all. That mechanism — not caching — is why a CDN accelerates even a completely uncacheable response (§7).
Hold this: latency is pipe length, bandwidth is pipe width, throughput is actual flow, and their product (BDP) is how much data must be in flight to keep the pipe full. Long RTT means enormous BDP means TCP struggles.
0.6TCP slow start and the congestion window — why long RTT throttles transfer#
The BDP above says how much data must be in flight. This section explains why TCP, left to itself, refuses to put that much in flight for a long time. This is the mechanism that makes edge termination (§3.3, §7) such a large win, and it is the prerequisite that candidates almost never have.
Why congestion control exists at all. In October 1986, the link between Lawrence Berkeley Laboratory and UC Berkeley — 400 yards apart — collapsed from 32 kbps to 40 bps, a factor of 1,000. The cause, diagnosed by Van Jacobson, was congestion collapse: senders transmitting faster than the bottleneck router could forward, the router's queue overflowing, packets dropping, senders retransmitting the lost packets on top of their existing send rate, and the whole system spiralling into a state where nearly all transmitted bytes were retransmissions of already-retransmitted data. The fix, shipped in 4.3BSD in 1988 and now in every TCP stack on earth, was to give each sender a self-imposed speed limit that starts small and probes upward until the network pushes back. That limit is the congestion window.
**Sub-Concept:
cwnd— the congestion window. The congestion window (cwnd)** is a variable held by the sender stating the maximum number of unacknowledged bytes it will allow itself to have in flight. It is entirely the sender's own invention — no packet on the wire ever contains it, and the receiver never sees it. It exists alongside a second, different limit: **rwnd, the receive window**, which is advertised on the wire (it is the 16-bit window field of §0.5) and states how much buffer space the receiver has free. **The sender may havemin(cwnd, rwnd)bytes outstanding.**rwndprotects the receiver from being overrun (that is flow control);cwndprotects the network from being overrun (that is congestion control). Confusing the two is a classic interview stumble; keep them straight by remembering **rwndis about the endpoint's memory,cwndis about the path's capacity.**
cwndis measured in bytes but is universally discussed in units of MSS (Maximum Segment Size) — the largest chunk of application data one TCP segment carries, which on a standard 1500-byte-MTU Ethernet path is 1460 bytes (1500 minus 20 bytes of IP header minus 20 bytes of TCP header; see File 01 §0.5). So "cwnd= 10" means ten segments, about 14,600 bytes, and that number is about to matter a great deal.
Slow start, step by step, with real numbers. When a TCP connection opens, the sender has no idea what the path can carry, so it starts conservatively and doubles every round trip:
- **
cwndbegins at the initial window (IW). RFC 6928 (2013) raised the standard initial window to 10 segments ≈ 14.6 KB**; before that it was 3 segments (~4.4 KB), and before that 1–2 segments. Modern Linux uses IW10 by default (ip route change ... initcwnd 10), and some CDNs deliberately raise it further on paths they trust. - **The sender transmits
cwndbytes and stops**, waiting for acknowledgements. - **For each acknowledgement received,
cwndgrows by 1 MSS.** Since a full window's worth of acknowledgements arrives per RTT, and there werecwndsegments in that window, **cwnddoubles every RTT.** ("Slow start" is a spectacular misnomer — the growth is exponential. It is called "slow" only relative to the previous behaviour of blasting a full receive window immediately.) - Growth continues until one of three things happens:
cwndreachesrwnd(the receiver is the limit);cwndreachesssthresh, the slow-start threshold, at which point the algorithm switches from exponential growth to the linear congestion avoidance phase (+1 MSS per RTT instead of doubling); or a packet is lost, which TCP interprets as the network's only signal that it is full.
Now the table that makes the point. How long does it take to transfer a 1 MB file, purely as a function of RTT, given slow start from IW10? Assume no loss and an unlimited receiver window, and count only the transfer (not the handshake):
RTT # cwnd (segments) bytes this RTT cumulative
1 10 14.6 KB 14.6 KB
2 20 29.2 KB 43.8 KB
3 40 58.4 KB 102.2 KB
4 80 116.8 KB 219.0 KB
5 160 233.6 KB 452.6 KB
6 320 467.2 KB 919.8 KB
7 640 934.4 KB 1,854.2 KB <-- 1 MB done during RTT 7Seven round trips to move one megabyte, regardless of how much bandwidth you have. Now price those round trips:
| Path | RTT | Time to transfer 1 MB (slow start, no loss) | Effective throughput |
|---|---|---|---|
| User → edge in same metro | 10 ms | 7 × 10 ms = 70 ms | ~117 Mbps |
| User (Sydney) → origin (Virginia) | 220 ms | 7 × 220 ms = 1,540 ms | ~5.3 Mbps |
Both users may have identical gigabit connections. The distant one gets 5 Mbps and the nearby one gets 117 Mbps, and the only difference is RTT. This is the concrete, mechanical answer to "why does a CDN help so much?" — not merely "it's closer," but "TCP's ramp is measured in round trips, so a shorter round trip makes the ramp itself 22× faster." Say that sentence in an interview and you will be visibly ahead of the candidate who says "it caches stuff nearby."
Loss makes it dramatically worse, and distance causes loss. When a packet is lost, the sender's reaction depends on the congestion-control algorithm:
- TCP Reno / NewReno (the classic): on detecting loss via three duplicate acknowledgements, halve
cwndand enter congestion avoidance ("fast recovery"). On a full retransmission timeout (RTO) — no acknowledgement at all within the timeout, which is computed from measured RTT and its variance — collapsecwndall the way back to 1 segment and slow-start again. On a 220 ms path, recovering from that is seconds. - TCP CUBIC (the Linux default since 2.6.19): replaces the linear growth of congestion avoidance with a cubic function of time since the last congestion event rather than of round trips. Because it grows on a wall-clock schedule rather than an RTT schedule, it recovers far better on long paths and is much fairer between flows of very different RTTs. This is why it won.
- BBR (Bottleneck Bandwidth and Round-trip propagation time, Google, 2016): abandons loss-as-congestion-signal entirely. It continuously estimates the path's actual bottleneck bandwidth and its minimum RTT, and paces sending to exactly
bandwidth × min_RTT. Why this matters enormously for CDNs: on paths with random, non-congestion loss — wireless, mobile, long-haul international — Reno and CUBIC misinterpret a corrupted-radio-frame loss as "the network is congested" and halve their rate for no reason. BBR does not. Google reported deploying BBR on YouTube produced median throughput gains of 4% globally and 14% in some countries, with far larger gains on lossy paths. Most large CDNs run BBR or a proprietary derivative on the edge→client path, and this is a legitimate, checkable differentiator between providers.
The cross-layer consequence, which is the real prerequisite payoff. Because loss probability compounds per hop and per kilometre, a long path is not merely slower — it is lossier, and TCP punishes loss in units of RTT. So the penalties multiply: more RTTs to ramp, longer RTTs, more loss events, and more expensive recovery per loss. **Terminating the TCP connection at an edge 10 ms away splits one long, lossy, slow-ramping connection into two short ones — a 10 ms user↔edge connection that ramps in milliseconds, and a long-lived, already-fully-ramped, permanently-warm edge↔origin connection whose cwnd is large because it has been open for hours.** That single sentence is the mechanism behind §7's claim that a CDN accelerates even uncacheable content.
Hold this: TCP starts at ~14.6 KB and doubles per round trip, so transfer time is measured in RTTs, not in bandwidth; a 22× longer RTT is a 22× slower ramp; and splitting the connection at the edge lets both halves run at their best.
0.7Autonomous Systems, BGP, peering and transit — how the internet actually routes#
Section 4 will claim that "BGP delivers the packet to the nearest PoP." That sentence is meaningless without knowing what BGP is, what "nearest" means to it, and why it frequently disagrees with geography. This is also the prerequisite that connects to File 01 §2.2's Virtual IP (VIP) concept — an anycast address is precisely a VIP whose "cluster" is the entire planet.
The internet is not a network. It is ~75,000 networks that agreed to exchange traffic.
Sub-Concept: the Autonomous System (AS) and the ASN. An Autonomous System is a collection of IP prefixes under a single, coherent routing policy operated by one organization. Comcast is an AS. Deutsche Telekom is an AS. Google is an AS (several, in fact). Your university might be one. Each is identified by an ASN (Autonomous System Number), originally a 16-bit integer (0–65535) and since 2007 a 32-bit one, allocated by the regional internet registries (ARIN, RIPE NCC, APNIC, LACNIC, AFRINIC). You should recognize a few on sight because they appear in traceroutes and looking-glass output constantly: AS13335 is Cloudflare, AS15169 is Google, AS16509 is Amazon, AS32934 is Meta/Facebook, AS2906 is Netflix, AS20940 is Akamai's main network, AS7018 is AT&T, AS3356 is Lumen/Level 3 — historically the largest transit network in the world. Why it exists: routing every individual IP address globally is impossible (there are 4.3 billion IPv4 addresses); routing to ~75,000 policy domains that each aggregate large address blocks is tractable. The AS is the unit of internet routing, and BGP's entire job is to compute paths between ASes.
Sub-Concept: BGP (Border Gateway Protocol) — what it is and, crucially, what it is not. BGP (currently BGP-4, RFC 4271) is the protocol by which autonomous systems announce to each other which IP prefixes they can reach and by what path. Two routers in different ASes establish a long-lived TCP connection on port 179 — note that: the protocol that runs the internet runs over TCP like any other application — and exchange UPDATE messages. An UPDATE says, in effect: *"I can reach the prefix
198.51.100.0/24, and the path to get there traverses these autonomous systems in this order:AS64500 AS13335."* That ordered list is the AS_PATH attribute, and it is the heart of BGP.Where it sits: BGP is an exterior gateway protocol — it routes between organizations. Inside a single organization, a different family of protocols (OSPF, IS-IS) computes routes within the network; those are interior gateway protocols and they genuinely optimize for a cost metric that usually correlates with link speed and latency. Do not confuse the two: your packets are steered by IS-IS inside an ISP and by BGP between ISPs.
**The critical property, stated precisely: BGP is a path-vector policy protocol, not a shortest-path protocol, and it has no concept of latency, bandwidth, congestion, or geography whatsoever.** There is no field in a BGP message for "this path is 40 ms." A router choosing among several announcements of the same prefix runs a fixed decision process, and the order of the tie-breakers tells you everything about why internet routing is sometimes bizarre:
1. **Highest
LOCAL_PREF** — a purely local, purely commercial number the network operator sets by hand. Its universal use is: prefer routes learned from customers (who pay me) over routes learned from peers (free) over routes learned from transit providers (whom I pay). Money outranks every technical consideration, and it does so at step one. 2. **ShortestAS_PATH** — fewest autonomous systems traversed. Note this counts organizations, not routers, not kilometres, not milliseconds. A path across one enormous global AS counts as "1" even if it physically circles the planet; a path through three small, adjacent, city-local ASes counts as "3." 3. **LowestORIGINtype, then lowestMED(Multi-Exit Discriminator) — a hint from a neighbour about which of several links into their network to prefer. 4. Prefer eBGP-learned over iBGP-learned, then lowest interior cost to the exit point (this is the famous hot-potato routing**: hand the traffic off to the neighbouring network at the geographically nearest exit, so it spends the least time on your backbone and the most on theirs). 5. Lowest router ID — an arbitrary deterministic tiebreak.What breaks, and how you diagnose it. Because step 1 is commercial and step 2 counts organizations rather than distance, BGP routinely produces paths that are geographically absurd. Traffic between two ISPs in the same African or South American city has historically been routed via Europe or Miami, adding 200+ ms, because neither ISP peered locally and both bought transit from a provider whose nearest exchange point was on another continent — a phenomenon known as tromboning or trombone routing. You diagnose it with
traceroute(which reveals the hop-by-hop path and, via reverse-DNS names that usually encode airport codes —ae-1.r02.lond03.uk.bb.example.netis London — the physical geography), withmtr(a continuous traceroute showing per-hop loss and latency), or with a looking glass — a public web interface on someone else's router that runsshow ip bgp <prefix>and prints the actual AS_PATHs that router is considering.The other thing that breaks: BGP has essentially no built-in security. A router accepts an announcement largely because a neighbour said it. When a network announces a prefix it does not own — by accident or maliciously — that is a BGP hijack, and traffic for those addresses flows to the wrong place globally within minutes. Famous incidents: Pakistan Telecom took YouTube offline worldwide in 2008 by announcing YouTube's prefix internally to censor it and leaking the announcement to its transit provider; in April 2018 attackers hijacked Amazon's Route 53 DNS prefixes and used the resulting DNS control to steal roughly $150,000 of cryptocurrency from MyEtherWallet users. The mitigations are RPKI (Resource Public Key Infrastructure), a cryptographic database in which address holders publish signed ROAs (Route Origin Authorizations) stating "only AS13335 may originate this prefix," and route filtering by transit providers who check announcements against RPKI and the IRR (Internet Routing Registry) databases. Why a CDN customer should care: your CDN's ability to keep serving you depends on nobody successfully hijacking its anycast prefixes, and mature providers publish their RPKI posture. It is a fair and impressive question to ask a vendor.
Sub-Concept: transit, peering, and why "free" traffic exchange determines CDN placement. Two ASes can have exactly two kinds of commercial relationship, and the difference drives the entire economics of edge placement.
Transit is buying internet access. A smaller network pays a larger one to carry its traffic to everywhere — the transit provider announces the customer's prefixes to the whole internet and accepts traffic destined for it. Pricing is per Mbps of the 95th-percentile of measured throughput (samples every 5 minutes over a month, discard the top 5% of samples, bill on the highest remaining — a convention that deliberately forgives short spikes). Prices have collapsed over two decades from $1,200/Mbps/month in 1998 to roughly $0.10–$0.30/Mbps/month in major markets today, and are still 5–20× higher in poorly-connected regions, which is exactly where CDNs deliver the biggest wins.
Peering is swapping traffic. Two networks connect directly and exchange traffic destined for each other's customers at no charge to either party (this is settlement-free peering). Each saves the transit fee it would otherwise pay to reach the other, and both get a shorter, lower-latency, more controllable path. Peering happens either privately — a dedicated fibre cross-connect between two organizations' routers in the same building, called a PNI (Private Network Interconnect) — or publicly at an IXP (Internet Exchange Point): a shared Ethernet switching fabric in a neutral facility where hundreds of networks each plug in once and can then peer with any of the others. The largest IXPs are enormous: DE-CIX Frankfurt peaks above 17 Tbps with 1,000+ connected networks; AMS-IX Amsterdam and LINX London are of the same order.
Why this dictates where PoPs go. Putting a PoP inside an IXP building means one cross-connect gives you a direct, settlement-free, one-hop path to the users of dozens or hundreds of ISPs simultaneously. That is: lowest possible latency (one AS hop, no transit provider's backbone in the middle), lowest possible cost (settlement-free rather than per-Mbps transit), and most control (a direct link you can monitor, rather than a path chosen by someone else's BGP policy). "Number of PoPs" is the marketing number; "number of peering sessions and IXPs present at" is the number that actually predicts performance. Cloudflare publicly reports peering with 13,000+ networks; Akamai's differentiator is going one step further and placing servers inside ISP networks (§2.14).
Hold this: the internet is 75,000 ASes glued together by BGP; BGP picks paths by commercial policy first and organization-count second, and never by latency or distance; peering at IXPs is how a CDN buys a short, cheap, one-hop path to millions of users.
0.8Anycast from first principles#
You now have every piece needed to understand anycast properly rather than as magic. Section 4.2 will use it; this defines it.
The four IP addressing modes, so the word has a contrast to sit against. Unicast is one address, one destination interface — the normal case, and how ~all of the internet works. Broadcast is one address, every interface on the local segment (255.255.255.255, or ff:ff:ff:ff:ff:ff at Layer 2 — see File 01 §2.8); it does not cross routers and does not exist in IPv6 at all. Multicast is one address, every interface that has joined a specific group — used for IPTV and market-data feeds, and largely absent from the public internet because it requires cooperation from every network in the path. Anycast is **one address configured on many interfaces in many places, where the network delivers each packet to exactly one of them — whichever one the routing system considers closest.**
The mechanism, with concrete values. Suppose a CDN owns the prefix 198.51.100.0/24. It configures the address 198.51.100.42 on servers in Sydney, Tokyo, Frankfurt and Virginia, and from each of those four locations it establishes BGP sessions with local ISPs and IXP participants and **announces the identical prefix 198.51.100.0/24**. Now consider a router inside an Australian ISP. It receives, via its various BGP neighbours, several announcements for that same prefix:
198.51.100.0/24 via AS7545 (local IXP peer) AS_PATH: 64500 <- 1 hop
198.51.100.0/24 via AS3356 (transit provider) AS_PATH: 3356 64500 <- 2 hops
198.51.100.0/24 via AS2914 (transit provider) AS_PATH: 2914 1299 64500 <- 3 hopsIt runs the decision process from §0.7, picks the first (LOCAL_PREF for peer routes, then shortest AS_PATH), and installs it. **Every packet that Australian ISP's customers send to 198.51.100.42 now goes to Sydney — not because anything knows where Sydney is, but because that announcement won the BGP tiebreak.** A German ISP's router runs the same process against its announcements and lands on Frankfurt. There is no central coordinator, no geolocation database, no measurement. Proximity is an emergent property of BGP's own preference for short, peer-learned paths.
Why it works despite sounding impossible. People's first objection is "surely the packets get split between locations and the connection breaks?" They do not, because of one property: routing is deterministic per router. A given router has one installed best path for the prefix at a given moment, so every packet of a given flow arriving at that router goes the same way. As long as (a) the flow's packets keep arriving at the same routers and (b) no BGP path change occurs mid-flow, the entire TCP connection lands consistently at one PoP.
Where that guarantee frays — the three real failure modes.
- A BGP reconvergence mid-flow. If a link fails or a better path appears while your TCP connection is open, the router may install a different best path and your subsequent packets arrive at a different PoP, which has no state for your connection and answers with a
RST(TCP reset), killing it. For a 200 ms HTTP request this is vanishingly rare and irrelevant. For a multi-hour WebSocket connection, a large file upload, or a video conference, it is a real, observed problem — this is the "flow-stability caveat" of §4.2, and it is why raw anycast is a poor fit for long-lived stateful connections without extra machinery. The industry mitigation is a consistent-hashing layer inside each PoP plus flow-state sharing (Cloudflare's Unimog and Google's Maglev, File 01 §9.1, both solve exactly this), or simply preferring TCP-terminating designs where the reconnect is cheap. - ECMP within a site. ECMP (Equal-Cost Multi-Path) is a router feature that spreads traffic across several equally-good next hops. It hashes the packet's 5-tuple (source IP, source port, destination IP, destination port, protocol) to pick a path, which keeps each flow pinned to one path. Fine — until the set of next hops changes (a server is added or removed), at which point the hash buckets shift and existing flows get rehashed to different servers. This is precisely the problem consistent hashing (File 06) exists to solve, and it is why Maglev-style hashing is a load-balancer requirement rather than a nicety.
- "Nearest" is BGP-nearest, not latency-nearest. Because AS_PATH counts organizations and LOCAL_PREF encodes money (§0.7), a user can be routed to a PoP that is one AS hop away but 3,000 km distant, in preference to one that is three AS hops away but in the same city. Real, measured examples of this abound — users in New Zealand landing in Los Angeles rather than Sydney, users in India landing in Singapore rather than Mumbai. Providers correct it by adjusting their announcements: AS_PATH prepending (announcing your own ASN two or three times in a row, artificially inflating the path length so that announcement loses the tiebreak and traffic shifts elsewhere), selective announcement (not announcing a prefix at certain PoPs at all), BGP communities (numeric tags attached to an announcement that request specific handling from the receiving network — e.g. "do not export this to your transit providers"), and more-specific announcements (announcing a
/24from one site and only a/22elsewhere, since routers always prefer the longest prefix match regardless of every other attribute — this is the biggest hammer in the toolbox and the one used to steer traffic decisively).
The advantages that follow directly from the mechanism, not asserted but derived:
- Zero client-side logic and zero DNS dependency. The address is the routing. A hard-coded IP, a client that ignores DNS TTLs, a mobile app that resolved once at install time — all of them still land on the nearest PoP, because the steering happens in the routers, below the application entirely. This is anycast's single biggest structural advantage over GeoDNS, which is helpless against a client that caches the wrong IP.
- Failover at BGP speed, not TTL speed. When a PoP goes down, its BGP sessions drop (or it deliberately withdraws its announcement — an operation called draining, done in seconds by a control plane). Neighbouring routers remove that path and fall back to the next-best announcement. Convergence takes seconds to tens of seconds, versus DNS failover's TTL-bounded minutes-to-hours. Nothing is reconfigured and no record is edited.
- Volumetric DDoS absorption, which only anycast can provide. This is worth being precise about because it is the highest-value point in the whole security section (§10.1). A volumetric attack tries to exceed the capacity of the link into your infrastructure. Against a unicast address, all attack traffic converges on one location and saturates one site's ingress. Against an anycast address, each attacking source's packets are drawn to the attacker's own nearest PoP by the same BGP process that draws legitimate users — so a botnet distributed across 100 countries is automatically shattered across 100 PoPs, each of which absorbs 1/100th of it locally, close to the source, without any of it ever crossing the CDN's backbone. The defence scales with the attacker's own distribution: the more globally spread the botnet, the more thoroughly the attack dilutes itself. This is why the largest attacks ever recorded (Cloudflare mitigated a 71 million requests-per-second HTTP attack in February 2023 and a 201 million rps attack during the HTTP/2 Rapid Reset campaign in October 2023) are absorbed rather than merely survived.
- Cost and simplicity. One IP address to publish, one certificate, one DNS record, one firewall rule for customers to whitelist — for every region on earth.
Who uses it, so the term is grounded: all thirteen DNS root servers are anycast (that is how 13 names serve the planet); **Google Public DNS 8.8.8.8 and Cloudflare 1.1.1.1 are anycast; Cloudflare anycasts every single customer IP from every PoP, which is the most aggressive deployment in the industry; AWS Global Accelerator** (§14.5) sells anycast entry points without caching; GCP's Global External HTTP(S) Load Balancer uses a single anycast VIP worldwide (File 01 §9.3).
Hold this: anycast is one IP announced from many places via BGP; the routers, following commercial policy and AS-hop count, deliver each user to one nearby copy; it needs no client cooperation, fails over in seconds, and is the only mechanism that dilutes a volumetric DDoS by construction.
1Architectural Definition & "The Why"#
1.1The Plain Definition#
A Content Delivery Network (CDN) is a geographically distributed network of caching proxy servers (called edge servers or Points of Presence / PoPs) that store copies of your content physically close to end users, so that requests are served from a nearby edge instead of traveling all the way to your origin server (your actual backend/data center).
A CDN is, at its heart, caching (File 02) plus geography plus smart routing (File 01). It's a cache that lives all over the world.
1.2"The Why" — The Speed of Light Is the Enemy#
Two hard physical realities forced CDNs into existence:
(1) Latency is bounded by the speed of light. Data in fiber travels at roughly 2/3 the speed of light. A round trip from Sydney to a server in Virginia (~16,000 km each way) takes ~160–200 ms minimum — no amount of faster CPUs or bigger servers can beat physics. For a page that needs dozens of round trips (DNS, TCP, TLS, HTML, then CSS/JS/images), those hundreds of milliseconds stack into seconds of load time. Users abandon slow pages; every 100 ms of latency measurably costs conversions/revenue (Amazon's famous finding). The only fix for distance latency is to reduce the distance — put the content near the user. That is the CDN's entire reason to exist.
(2) Origin bandwidth and load don't scale to the whole planet. If a video, a software update, or a viral image is fetched by 50 million people, serving all of that from your origin means:
- Your origin's NIC/bandwidth saturates (you'd need enormous, expensive egress capacity).
- Your origin melts under the request volume (millions of concurrent connections).
- Your egress bandwidth bill is astronomical (cloud egress is pricey).
A CDN absorbs this: the origin serves each unique object once (or a few times) to the CDN, and the CDN's thousands of edge servers serve the millions of copies to users. This is origin offload — often 90–99% of traffic never touches your origin.
1.3The Problems CDNs Solve#
| Problem | How the CDN solves it |
|---|---|
| High latency for distant users | Serve from an edge PoP near the user (reduce distance) |
| Origin bandwidth saturation | Edges serve most traffic; origin offloaded 90–99% |
| Origin overload / flash crowds | Edge fleet absorbs spikes; only misses reach origin |
| DDoS attacks | Massive edge capacity absorbs/filters volumetric attacks |
| Slow static asset delivery | Cache images/CSS/JS/video at the edge |
| Cost of egress | Cheaper CDN egress + far fewer origin fetches |
Connecting to prior files: File 01 ended by noting single-region latency for far-away users needs geo routing; File 02 is caching in general. A CDN is the specific, industrial-scale answer: a globally distributed cache with geo-aware routing.
2The Recursive Sub-Concept Tree#
2.1Sub-Concept: Origin Server#
The origin is the authoritative source of the content — your web servers / object storage (e.g., an S3 bucket) / application backend. The CDN sits in front of the origin. On a cache miss, the edge fetches from the origin (an origin fetch / origin pull). A key design goal is minimizing origin fetches (maximizing offload).
2.2Sub-Concept: Edge Server / PoP (Point of Presence)#
An edge server is a caching proxy in the CDN's fleet. A PoP (Point of Presence) is a physical location (a data center) housing many edge servers, positioned in major metro areas worldwide. PoPs are often placed in/near an IXP (Internet Exchange Point) — a physical facility where many networks (ISPs, clouds, CDNs) plug into a shared switching fabric and exchange traffic directly with each other instead of paying an intermediate carrier to haul it; sitting at an IXP means the CDN is one hop from dozens of ISPs' users at once, which is exactly the low-latency, low-cost position a cache wants. Big CDNs have hundreds of PoPs across the globe. "The edge" collectively = all of them. Users are routed to a nearby PoP.
2.3Sub-Concept: Push vs. Pull CDN#
- Pull CDN (the default): you don't pre-upload anything. On the first request for an object at a given edge, the edge has a miss, pulls it from the origin, caches it, and serves it. Subsequent requests are hits. Lazy loading (like cache-aside from File 02), applied geographically. Simple; origin is the source of truth.
- Push CDN: you proactively upload/publish content to the CDN ahead of demand. Used for large files you know will be popular (a game release, a big video) so the very first user isn't slow and the origin isn't hit by the initial fan-out. More control, more management overhead.
Those two bullets are the summary. Push versus pull is a genuine strategy choice with a mechanism, a worked example, complexity, and decision conditions, so Rule 4 applies in full. Here it is properly.
2.3.1 Pull CDN — full treatment#
Mechanism, step by step. You change nothing about how content is stored. You point a hostname at the CDN (a CNAME, §0.3.1) and configure an origin — the hostname or bucket the CDN should fetch from on a miss.
- A user requests
https://cdn.example.com/hero.jpg. Anycast or GeoDNS lands them on the Frankfurt PoP. - The Frankfurt edge computes the cache key (§2.7) for that request and looks it up. Nothing found: a MISS.
- The edge (or its shield, §5.4) opens or reuses a connection to
origin.example.comand issuesGET /hero.jpg, adding conditional headers if it holds a stale copy. - The origin responds
200 OKwith the 240 KB body andCache-Control: public, max-age=86400. - The edge writes the object to its cache keyed as computed, records an expiry timestamp of
now + 86400 s, and streams the body to the user while it is still writing — a behaviour called streaming miss or pass-through fill, which matters because it means a miss costs the user the origin latency but not an extra buffering delay. - Every subsequent Frankfurt request for that key within 24 hours is a HIT served from local disk or RAM in single-digit milliseconds.
Worked example with real numbers. A site serves 500 distinct images and receives 10 million image requests per day spread across 100 PoPs, with a 24-hour TTL. Origin requests per day = 500 objects × 100 PoPs × 1 fill/day = 50,000 (and with an origin shield, §5.4, it collapses to roughly 500). Out of 10,000,000 user requests, the origin sees 50,000 — an offload of 99.5%, or 99.995% with a shield. The 50,000 "slow" users (0.5% of traffic) pay one extra origin round trip each.
Pros, with the reason each is true. Zero operational burden — there is no publish step, no sync job, no state to reconcile, because the cache is populated as a side effect of real demand; the CDN is a pure read-through layer and the origin remains the sole source of truth. Automatically correct — because content is only ever fetched from the origin, an object can never be "stale in the CDN because someone forgot to re-publish"; freshness is governed entirely by TTL and validators. Storage-efficient and demand-shaped — each PoP only stores what its own users actually asked for, so a PoP in São Paulo holds Brazilian-popular objects and one in Seoul holds Korean-popular ones, without anyone configuring that. Trivially scalable to enormous catalogues — a site with 50 million images does not need 50 million objects × 100 PoPs of storage; it needs only the working set (File 02 §2.6).
Cons, with the failure mode. The first request per object per PoP is slow — the cold-miss penalty. With 100 PoPs and a 24-hour TTL, every object is fetched from origin 100 times a day and 100 unlucky users per object per day eat the full origin RTT. For a Sydney user pulling from a Virginia origin, that is a 220 ms penalty on top of everything else. Unpopular content never gets warm — an object requested twice a week at a given PoP, with a 24-hour TTL, is a miss essentially every time; the cache does nothing for the long tail. This is the one-hit-wonder problem, and measurements at large CDNs consistently find that 50–70% of distinct objects are requested exactly once at a given PoP, meaning they cost a fill and provide no benefit — which is why edges use admission policies (cache only on the second request, or use a Bloom filter — a compact probabilistic set that answers "have I seen this key before?" in a few bits per key with a tunable false-positive rate — to detect a second sighting cheaply). A traffic spike on cold content still hammers the origin — a product launch drives simultaneous misses at every PoP at once, which is exactly the thundering herd of File 02 §6.3 and exactly why origin shield and request collapsing exist (§2.11, §5.4).
Complexity/cost. Setup: minutes (one DNS record and an origin hostname). Ongoing operational cost: near zero. Origin request volume: O(objects × PoPs / TTL) without a shield, O(objects / TTL) with one. Storage at each PoP: the local working set, self-managing by eviction.
When to use it. Essentially always, for essentially everything on the web — this is the default and you should need a specific reason to deviate. Especially when the catalogue is large and access is skewed (a few objects get most requests), when content changes on an unpredictable schedule, and when you do not want a deployment pipeline that must know about your CDN.
2.3.2 Push CDN — full treatment#
Mechanism, step by step. You take responsibility for populating the cache before demand arrives.
- Your build or publishing pipeline produces the artifacts (a new game patch, tomorrow's episode encoded into 12 bitrate ladders, a firmware image).
- The pipeline uploads them to the CDN's storage or ingest API — historically over FTP/rsync, today over an HTTP API or by writing to the provider's own origin storage (Cloudflare R2, Fastly's Object Storage, Akamai NetStorage, CloudFront with an S3 origin plus a pre-warm job).
- The CDN replicates the objects out to PoPs — either to all of them, or to a chosen subset, on a schedule you control (typically off-peak, when spare backbone capacity is free).
- When the first user asks, every PoP is already a hit. There is no cold miss anywhere, ever.
- You are now responsible for deletion. Content stays until you remove it, so a stale or superseded object lingers and consumes paid storage until your pipeline cleans it up.
Worked example — why Netflix cannot use pull. Netflix's catalogue is on the order of hundreds of terabytes once every title is encoded into its full bitrate ladder. At 8 pm on a Friday, tens of millions of people press play within the same hour. Under a pull model, the first viewer of each title in each region triggers a multi-gigabyte origin fetch, and the aggregate first-fetch traffic at peak hour would be enormous, over exactly the links that are most congested at exactly the moment they are most congested. Instead, Open Connect (§15.1) pushes: at 3 am local time, when the ISP's network is nearly idle and transit is effectively free, Netflix's control plane copies the titles its recommendation system predicts each region will want onto the appliances sitting inside that region's ISPs. The fill happens on a network that is empty, and the serving happens from a box that is already inside the user's ISP. Netflix reports its predictive fill achieves cache-hit rates above 95% from local appliances. This is the entire argument for push at scale: it lets you move the bytes at a time and over a path of your choosing, rather than at the time and over the path your users' demand dictates.
Pros, with the reason. No cold-miss penalty, ever — the first user is as fast as the millionth, which matters enormously when the "first user" is a million people simultaneously at a launch moment. Fill traffic is scheduled — you move bytes when bandwidth is cheap and links are idle, converting a peak-hour cost into an off-peak one, which for a video service is the difference between viable and ruinous economics. Guaranteed availability of specific content — you know a given file is on a given PoP because you put it there, which is what you need for a coordinated global launch. The origin can be offline — there is nothing to pull from, so origin capacity, origin uptime and origin egress are removed from the equation entirely.
Cons, with the failure mode. You now operate a distributed publishing system, with everything that implies: partial failures (the push succeeded to 240 PoPs and failed to 12 — now some users get 404s), retries, versioning, and reconciliation. You pay storage for everything, everywhere, forever — including content nobody requests. Pushing a 50-million-object catalogue to 300 PoPs is 15 billion object-copies; the arithmetic simply does not close. Deletion becomes your problem — stale content persists until explicitly removed, so a bug in the cleanup job means users are served last week's build indefinitely. Publish latency enters your critical path — an emergency fix is not live until the push completes, which for a large artifact across a global fleet is minutes, not milliseconds.
Complexity/cost. Setup: significant (a pipeline, an ingest integration, verification, cleanup). Storage cost: O(objects × PoPs), paid continuously. Publish time: O(bytes × PoPs / fill bandwidth). Origin request volume: zero.
When to use it. When the content set is small and known in advance; when demand is simultaneous and predictable (a game release, a launch keynote, an OS update, a sports event); when the objects are very large so a cold miss is not 220 ms but 30 seconds; and when you control the release schedule and can therefore pre-position. In practice, very few organizations run a pure push CDN — the common real-world shape is pull with pre-warming, described next.
2.3.3 The hybrid everyone actually uses: pull + pre-warm#
The honest answer to "push or pull?" in a modern interview is: pull as the architecture, with selective pre-warming as an operation. You run a standard pull CDN, and immediately before a known demand spike you deliberately manufacture misses so the fill happens on your schedule rather than your users'. The mechanisms:
- Provider pre-fetch APIs. Several CDNs expose an explicit "load this URL into cache at these PoPs" call. Akamai's Fast Purge's sibling prefetch, Fastly's ability to issue a synthetic request from every PoP, and CloudFront's regional edge caches all support variants of this.
- A synthetic-request sweep. Since anycast means "you get whichever PoP is nearest you," you can force fills across the fleet by issuing requests from many locations — a small script running on cheap VMs or a synthetic-monitoring provider in 30 cities, fetching the launch URLs a few minutes before go-live. Crude, cheap, and effective.
- Tiered caching does most of the work for you. With an origin shield (§5.4), the first PoP's miss warms the shield, so the other 299 PoPs' misses are served from the shield at 20–40 ms rather than from the origin at 220 ms. Pre-warming the shield alone captures most of the benefit of pre-warming everything, at 1/300th of the effort — this is the highest-leverage version of the technique and the one to name in an interview.
Decision rule, plainly stated. Use pull unless you can name a specific reason not to — it is the default for the entire web. Use push when the content is large, the catalogue is small, the demand moment is known, and you own the release schedule. Use pull with shield pre-warming when you want most of push's launch-moment benefit without operating a publishing system — which is the right answer for the overwhelming majority of real systems.
| Dimension | Pull CDN | Push CDN | Pull + pre-warm |
|---|---|---|---|
| Who populates the cache | User demand | Your pipeline | Demand, plus a deliberate sweep |
| First-request latency | Full origin RTT (cold miss) | Fast (already there) | Fast for pre-warmed URLs |
| Storage cost | Working set only, per PoP | Whole catalogue × every PoP | Working set only |
| Origin must be up | Yes, for fills | No | Yes, for fills |
| Deletion/cleanup | Automatic (TTL + eviction) | Your responsibility | Automatic |
| Scales to huge catalogues | Yes | No | Yes |
| Setup effort | Minutes | Weeks | Hours |
| Canonical user | Essentially all websites | Netflix Open Connect, game patches, OS updates | Any site with a known launch |
2.4Sub-Concept: Cache Hit Ratio at the Edge (and the "cache hierarchy")#
Same metric as File 02, now geographic. A high edge hit ratio means most requests are served locally (fast, origin offloaded). To boost it, CDNs use a multi-tier cache hierarchy: an edge miss doesn't go straight to origin — it checks a regional/parent cache (a "mid-tier" or shield) first. Only a miss there hits the origin. This dramatically cuts origin load (see origin shield, 5.4).
2.5Sub-Concept: TTL & Cache-Control Headers#
The origin tells the CDN how long to cache each object via HTTP response headers (from File 02's TTL concept, now driven by HTTP):
Cache-Control: max-age=3600→ cache for 1 hour.Cache-Control: no-store→ never cache.Cache-Control: private→ only the browser may cache, not shared CDN caches.Cache-Control: public→ any cache may store it.ETag/Last-Modified→ validators for revalidation (conditional requests, 5.2).s-maxage→ TTL specifically for shared caches (CDN), overridingmax-agefor the CDN.
2.6Sub-Concept: Anycast (the routing magic — full treatment in Section 4)#
Anycast is a network addressing scheme where **many physical servers, in many locations, all announce the same IP address to the internet. The internet's routing protocol (BGP) naturally delivers a user's packets to the topologically nearest** location announcing that IP. So a single IP "magically" resolves to whichever PoP is closest to each user. This is how many CDNs route users to the nearest edge without any application logic. Explained fully below.
3Deep-Dive Mechanics: How a CDN Serves a Request#
3.1End-to-End Flow (Pull CDN)#
User in Sydney wants https://cdn.example.com/logo.png Origin in Virginia (US)
1. DNS resolve cdn.example.com
-> CDN's DNS (or Anycast IP) returns the SYDNEY edge PoP address
2. User TCP+TLS handshake with SYDNEY edge (~5-20 ms, not 200 ms!)
3. GET /logo.png -> Sydney edge checks its cache
3a. HIT -> serve logo.png from Sydney. DONE. (fast, origin untouched)
3b. MISS -> edge asks its REGIONAL/SHIELD cache
- shield HIT -> fill Sydney edge, serve, cache it
- shield MISS -> ORIGIN PULL to Virginia (the one slow trip),
fill shield + edge, serve, cache per Cache-Control
4. Next Sydney user for /logo.png -> HIT at the Sydney edge (fast)The genius: the slow, long-distance trip to Virginia happens at most once per object per region (on the first miss). Every subsequent user in that region gets a fast local hit. Millions of users, one origin fetch.
3.2What CDNs Cache (and increasingly compute)#
- Static assets (classic): images, CSS, JS, fonts, video segments, downloads, PDFs. Immutable or slow-changing → ideal to cache with long TTLs.
- Dynamic/API responses (modern): short-TTL caching of API responses, personalized-but-cacheable fragments, and stale-while-revalidate for near-real-time data.
- Video streaming: CDNs are the backbone of streaming — they cache HLS/DASH segments (video chunked into small files) at the edge. This is the single biggest CDN use case by bandwidth.
- Edge compute (the frontier): modern CDNs run code at the edge (Cloudflare Workers, Lambda@Edge, Fastly Compute) — auth, A/B tests, header rewriting, personalization, even whole apps — executing near the user instead of at origin. This blurs the line between "CDN" and "distributed compute platform."
3.3TLS & Connection Termination at the Edge#
The edge terminates TLS (File 01 concept), so the expensive TLS handshake happens over the short user↔edge hop (~20 ms), not the long user↔origin hop (~200 ms). The edge keeps warm, reused (keep-alive) connections to the origin, so even origin pulls skip repeated handshakes. CDNs also terminate the newest protocols at the edge even if your origin only speaks HTTP/1.1 — instant protocol upgrades for users. Worth defining: HTTP/2 multiplexes many concurrent requests over one TCP connection (instead of HTTP/1.1's one-request-at-a-time per connection); HTTP/3 goes further by replacing TCP itself with QUIC — a transport protocol built on UDP that bakes in TLS, cuts the handshake to one round trip (zero for repeat visitors), and eliminates TCP's head-of-line blocking (in TCP, one lost packet stalls every multiplexed stream behind it until retransmitted; QUIC's streams are independent, so a loss stalls only its own stream). For a far-away, lossy mobile connection — exactly the users a CDN serves — these handshake and loss-recovery savings are the difference between snappy and sluggish.
4Anycast & Request Routing — How Users Find the Nearest Edge#
"Route the user to the nearest edge" is the core CDN problem. There are two main mechanisms; know both and their trade-offs.
4.1Sub-Concept: BGP (Border Gateway Protocol)#
BGP is the routing protocol of the internet — it's how independent networks (Autonomous Systems, e.g., ISPs, clouds, CDNs) tell each other "to reach IP block X, send traffic through me," and how routers pick paths between them. BGP chooses routes by policy and path length (roughly, fewest network hops). You need BGP to understand anycast.
4.2Anycast Routing#
Mechanism: The CDN announces the same IP prefix from all its PoPs via BGP. When a user sends a packet to that anycast IP, the internet's routers forward it to the BGP-nearest PoP announcing it. Different users, sending to the identical IP, land on different PoPs — each on the one closest to them.
- Pros: Automatic proximity routing with no DNS/app logic. Superb DDoS absorption — attack traffic to the anycast IP is spread across every PoP rather than concentrated, so the attack is diluted across the whole network's capacity. Fast failover: if a PoP dies, BGP just stops announcing there and traffic reroutes to the next-nearest PoP automatically.
- Cons: "Nearest" is measured in BGP hops/policy, not actual latency or geography — sometimes suboptimal (a "close" PoP by BGP may be worse by latency). Less granular control. Stateful connections can (rarely) get re-routed mid-session if BGP paths change (mostly a non-issue for short HTTP requests). Used by Cloudflare (heavily), Google.
4.3DNS-Based Routing (GeoDNS / GSLB)#
Mechanism: Routing is done at DNS resolution time. When the user's resolver asks "what's the IP for cdn.example.com?", the CDN's authoritative DNS looks at who is asking (the resolver's IP, or the client subnet via EDNS Client Subnet) and returns the IP of the best PoP for that location, factoring in geography, current PoP load, and health.
Sub-Concept: GSLB (Global Server Load Balancing). GSLB is load balancing across geographic regions/data centers (as opposed to File 01's LB within one). It uses DNS (and/or anycast) to steer users to the best region based on proximity, capacity, health, and policy (e.g., latency-based, geolocation, or weighted routing — exactly AWS Route 53's routing policies). It's the "which region?" layer sitting above the "which server in this region?" layer.
- Pros: Fine-grained control — can route by real latency measurements, PoP load, health, cost, and business rules. Can do gradual/weighted rollouts and failover between regions.
- Cons: DNS caching hurts agility — resolvers cache the answer for the TTL, so if a PoP dies, users with a cached DNS record keep hitting the dead PoP until the (short) TTL expires. Requires short DNS TTLs (which adds DNS lookup overhead). Sees the resolver's location, not the user's, unless EDNS Client Subnet is supported (a user on a distant DNS resolver can be misrouted). Used by Akamai (classically), AWS CloudFront (with Route 53).
4.4Anycast vs. DNS Routing — The Trade-off#
| Aspect | Anycast | DNS/GeoDNS (GSLB) |
|---|---|---|
| Proximity metric | BGP path (network topology) | Geo + latency + load + health |
| Failover speed | Fast (BGP reconverge) | Limited by DNS TTL caching |
| DDoS absorption | Excellent (spreads attack) | Weaker (IP is per-region) |
| Control granularity | Coarse | Fine (load/health/policy-aware) |
| Session stability | Rare re-route risk | Stable per resolution |
In practice CDNs combine them: anycast to get you to the nearest PoP region + internal load balancing (File 01) within the PoP, and/or DNS steering for policy control. Not either/or.
5Cache Control, Invalidation & Dynamic Content#
app.9f3a1c.js), set a one-year TTL, and a deploy simply
references a new URL. Purging is the emergency lever, not the routine mechanism.5.1Controlling What/How Long to Cache#
The origin drives caching via Cache-Control/s-maxage/ETag (2.5). Best practices:
- Long TTLs + content-hashed filenames for static assets: name files
app.9f2a3c.js(hash in the name). The content is immutable (Cache-Control: max-age=31536000, immutable) — cache it for a year. To "change" it, deploy a new filename (app.7b1d9e.js) referenced by updated HTML. This sidesteps invalidation entirely — the killer pattern for static assets ("cache-busting via fingerprinted URLs"). - Short TTLs for things that change (HTML, API responses).
- **
Varyheader** to cache different variants (e.g.,Vary: Accept-Encodingfor gzip/brotli,Vary: Accept-Language). Beware: too manyVarydimensions fragment the cache and kill hit ratio.
5.2Revalidation (Conditional Requests)#
When a cached object's TTL expires, the edge doesn't always re-download it. It sends a conditional request to the origin: If-None-Match: <ETag> or If-Modified-Since: <date>. If unchanged, the origin replies **304 Not Modified** (tiny, no body) and the edge just refreshes the TTL on its existing copy. Saves bandwidth — you only re-transfer when content actually changed.
5.3Purging / Invalidation#
To force-remove content before its TTL (e.g., you published a correction, or bad data got cached):
- Purge by URL — invalidate one object. Fast.
- Purge by tag/surrogate key — tag related objects (e.g., all pages showing product #42 tagged
product-42); one purge clears them all. The scalable way (Fastly pioneered surrogate keys). - Purge everything — nuclear option; causes a miss storm to the origin (all subsequent requests miss and pull) — basically a self-inflicted avalanche (File 02). Use sparingly.
Purges propagate to all PoPs; fast global purge (sub-second across hundreds of PoPs) is a headline CDN feature.
5.4Sub-Concept: Origin Shield#
An origin shield is a designated single PoP (or small tier) that sits between all other edges and the origin. All edge misses funnel through the shield; only shield misses hit the origin. Benefits:
- Collapses origin load: without a shield, a globally-viral object could miss at 300 PoPs simultaneously → 300 origin fetches. With a shield, the first PoP's miss goes to the shield, the shield fetches from origin once, and the other 299 PoPs get filled from the shield. Origin sees ~1 request instead of 300.
- Request collapsing / coalescing: even at a single PoP, many simultaneous misses for the same object are collapsed into one origin fetch (this is File 02's stampede/single-flight defense, at the edge). Origin shield extends this globally.
- Takeaway: origin shield = a mid-tier cache that maximizes origin offload and prevents thundering-herd on the origin.
5.5Caching Dynamic & Personalized Content#
Naively, "dynamic = uncacheable." Modern practice says otherwise:
- Micro-caching: cache even highly dynamic responses for a very short TTL (1–5s). Under high traffic, a 1s cache still turns thousands of req/s into one origin fetch/s — huge offload, negligible staleness.
- Edge-Side Includes (ESI) / fragment caching: cache the static page shell with long TTL, and stitch in the small dynamic/personalized fragment separately.
- Stale-while-revalidate / stale-if-error: serve the (slightly) stale cached copy instantly while refreshing in the background (or when the origin is down) — resilience + speed (File 02 pattern, standardized as HTTP headers).
- Edge compute: personalize at the edge (read a cookie, run logic in a Worker) without a round trip to origin.
6Edge Protocol Optimizations — TLS, HTTP/2, QUIC, Compression#
Section 5 covered what the edge caches. This section covers the other half of a CDN's value, which applies even when the cache misses: the edge speaks the transport protocols better than your origin possibly can, because it is physically close to the user and the protocols are all latency-sensitive.
6.1TLS at the edge — killing the handshake round trips#
Recall the round-trip accounting from §0: before a single byte of your HTML moves, the browser needs DNS resolution, a TCP handshake (1 RTT), and a TLS handshake (1 RTT for TLS 1.3, 2 for TLS 1.2). On a 150 ms transcontinental link that is 300–450 ms of pure setup. Terminate that at an edge 10 ms away and the same setup costs 20–30 ms — a saving that no amount of backend optimization could ever produce, because the backend was never the problem.
Session resumption removes even more. On a repeat visit, TLS lets the client present a session ticket — an encrypted blob containing the previously negotiated secret, which the server can decrypt and reuse — so the expensive asymmetric key exchange is skipped entirely (File 02 §2.6 covers the cryptography). The CDN-specific problem, and the reason this is worth teaching: a session ticket is only useful if the server that receives it can decrypt it. With hundreds of edge servers in a PoP and hundreds of PoPs, a returning user landing on a different machine gets a full handshake unless the ticket keys are shared. Every serious CDN therefore distributes and rotates a common set of session-ticket keys across its fleet — and does so carefully, because a ticket key that never rotates undermines forward secrecy (an attacker who eventually steals the key can decrypt every recorded session that used it). The trade-off in one line: share ticket keys widely for performance, rotate them frequently for security, and those two pull in opposite directions.
TLS 1.3 0-RTT goes further: on a resumed connection the client sends application data in its very first packet, alongside the handshake, for an effective zero round trips. The cost is a real security property: 0-RTT data is replayable — a network attacker who captures that first flight can re-send it, and the server cannot distinguish the copy from the original. That is harmless for a GET of a cacheable asset and dangerous for anything that changes state. The rule: enable 0-RTT for idempotent GETs only, never for POST/PUT/DELETE (File 15 covers idempotency properly). Every CDN that offers 0-RTT enforces some version of this rule, and knowing why it exists is the interview-grade answer.
6.2HTTP/2 — multiplexing, and the problem it did not solve#
HTTP/1.1's defect: one request at a time per connection. A page needing 80 assets either serialized them or forced the browser to open ~6 parallel connections per host (each with its own handshake and its own slow-start), which is why the era's optimizations were sprite sheets, file concatenation, and domain sharding — all workarounds for a protocol limit.
HTTP/2's fix — multiplexing. One TCP connection carries many concurrent streams, each an independent request/response, with frames from different streams interleaved on the wire. Eighty assets now travel over one warm connection. It adds HPACK header compression (headers repeat almost identically across requests; HPACK keeps a shared dynamic table so the second request's headers cost a handful of bytes instead of several hundred) and stream prioritization (the client can say "the stylesheet before the footer image").
What it did NOT fix, and this is the point of §6.3: TCP head-of-line blocking. All those streams ride one TCP connection, and TCP guarantees in-order delivery of the whole byte stream. Lose one packet belonging to the image, and TCP will not deliver any subsequent bytes to the application — including the completed stylesheet — until the lost packet is retransmitted. On a clean network HTTP/2 is a large win; on a lossy mobile network it can be worse than HTTP/1.1 with six connections, because six connections means a loss stalls only one sixth of your traffic. That surprise is exactly what motivated QUIC.
6.3HTTP/3 and QUIC — what actually changed#
QUIC is a transport protocol built on UDP rather than TCP, and HTTP/3 is HTTP mapped onto it. Building on UDP was not an aesthetic choice: TCP is implemented in operating-system kernels and in middleboxes across the internet, so changing it takes a decade; UDP is a thin wrapper the application can build on top of, so QUIC ships as a library and can evolve at software speed. Four concrete improvements:
- Per-stream loss recovery — the head-of-line fix. QUIC understands streams itself, so a lost packet stalls only the stream it belonged to. The stylesheet is delivered while the image's retransmission is still in flight. This is the single biggest win, and it is largest exactly where users suffer most: lossy mobile networks.
- Merged transport and crypto handshake. TCP+TLS 1.3 costs 2 RTTs (1 for TCP, 1 for TLS); QUIC folds them into 1 RTT, and 0 RTT on resumption, with the same replay caveat as §6.1.
- Connection migration. A TCP connection is identified by the 4-tuple of IPs and ports, so when your phone moves from Wi-Fi to cellular its IP changes and every connection breaks — which is why an app visibly stalls when you walk out of the house. QUIC identifies a connection by a connection ID that is independent of the IP address, so the session survives the network change intact.
- Encrypted transport metadata. Almost the entire QUIC header is encrypted, so middleboxes cannot inspect or "helpfully" rewrite it — which both improves privacy and prevents the protocol ossification that froze TCP.
The costs, stated honestly: QUIC runs in user space, so it consumes noticeably more CPU per byte than kernel TCP (a real cost at CDN scale, being closed by kernel offloads); some corporate firewalls block or throttle UDP, so clients must fall back to HTTP/2; and debugging is harder because the packets are encrypted. Deployment reality: browsers try HTTP/3 when advertised (via the Alt-Svc header or the DNS HTTPS record) and fall back silently, so it is a safe thing to enable at the edge — and this is precisely the kind of upgrade a CDN gives you for free, since your origin can keep speaking HTTP/1.1 while the edge speaks HTTP/3 to users.
6.4Compression at the edge#
Text compresses enormously — HTML, CSS, JavaScript, and JSON typically shrink 60–80% — and that reduction is multiplied by the number of users, making it one of the highest-leverage optimizations available. The algorithm choice is a CPU-versus-ratio trade:
- gzip — universal support, fast, ratio around 70% on text. The safe default.
- Brotli — Google's algorithm, roughly 15–25% smaller than gzip on typical text, achieved partly through a built-in dictionary of common web strings. At its highest compression levels it is slow, which is fine for static assets compressed once and cached, and unacceptable for dynamic responses compressed per request. The standard practice: Brotli at maximum level for cached static content, Brotli at a low level or gzip for dynamic responses.
- Zstandard — increasingly supported, offering gzip-like speed at Brotli-like ratios.
Negotiation happens through the Accept-Encoding request header, and the response must carry Vary: Accept-Encoding (File 02 §7.4) or a shared cache will hand a Brotli body to a client that cannot decode it. What not to compress: already-compressed formats (JPEG, PNG, WebP, MP4, ZIP) — you burn CPU to make them marginally larger.
Image and media optimization belongs here too, because it usually dwarfs text savings: the edge can transcode a JPEG to WebP or AVIF based on the client's Accept header (AVIF is commonly 50% smaller than JPEG at equal quality), resize to the device's actual display size, and strip metadata. Doing this at the edge rather than at build time means one canonical original serves every device — at the cost of a cache entry per variant, which again is a Vary and cache-key design problem.
7Dynamic Content Acceleration — Why a CDN Helps Even When Nothing Is Cacheable#
The most common misconception about CDNs is that they are only for static files. A CDN meaningfully accelerates a personalized, uncacheable API response, and the mechanism is worth understanding because it is the answer to "why put a CDN in front of an API?"
Where the time actually goes. Consider a user in Sydney calling an origin in Virginia, RTT ≈ 200 ms, with the origin taking 50 ms to compute the response.
DIRECT TO ORIGIN VIA CDN EDGE (5 ms away)
DNS ................ (cached) DNS ................ (cached)
TCP handshake ...... 200 ms TCP handshake ...... 10 ms
TLS 1.3 handshake .. 200 ms TLS 1.3 handshake .. 10 ms
Request + response . 200 ms + 50 ms Edge->origin (warm, no handshake,
already-open connection) 200 ms + 50 ms
TCP slow start: TCP slow start to user: negligible
several extra RTTs for a large body (short RTT, window grows in ms)
-------------------------------- --------------------------------
TOTAL ~ 650 ms+ TOTAL ~ 270 msFour distinct mechanisms produced that difference, and you should be able to name each:
- Handshake termination near the user (§6.1) — the two setup round trips shrink from 200 ms each to 10 ms each.
- Connection reuse to origin. The edge maintains a pool of long-lived, already-warm connections to your origin. The user's request does not pay for establishing one; it borrows an existing one. Over many users this is the difference between your origin handling millions of handshakes and handling almost none.
- TCP slow start avoidance — the underrated one. TCP does not begin at full speed; it starts with a small congestion window (about 10 packets, ~14 KB) and doubles it each round trip until it detects loss. Over a 200 ms RTT, growing the window enough to send 200 KB takes several round trips — so a large response is slow even on a fast link, purely because of RTT. On the edge-to-user leg the RTT is 10 ms, so the window grows to full size in tens of milliseconds. Meanwhile the edge-to-origin connection is long-lived and already has a fully-grown window. You have replaced one cold long-RTT connection with one warm long-RTT connection plus one short-RTT connection, and that is a large win independent of caching.
- Better routing. Public internet paths between two points are chosen by BGP for policy and cost, not for latency, and can be badly indirect. Traffic entering a CDN's edge travels the rest of the way over the provider's private backbone with optimized routing and no congested peering points — commonly 20–40% faster than the public path, and far more consistent.
The honest limits. If your origin takes 2 seconds to generate the response, the CDN saves you 400 ms of a 2.4-second experience — real, but your problem is the origin. And a CDN cannot help a first byte that must be computed. Say this in an interview: "a CDN removes network overhead, not compute time."
Techniques that convert 'uncacheable' into 'partly cacheable': cache the page shell and fetch the personalized fragment separately (so the shell is a global cache hit); use Edge Side Includes or edge compute (§9) to assemble a page from cached and dynamic fragments at the edge; and mark responses private, no-store only where genuinely necessary rather than reflexively across a whole API.
8Video & Large-File Delivery#
Video is where CDNs earn most of their revenue and where the mechanics differ enough from ordinary web delivery to deserve their own treatment.
8.1Why video cannot be delivered as one file#
A two-hour film at a good bitrate is several gigabytes. Delivering it as a single object would mean the viewer waits for a large prefix before playback, any network dip stalls the stream, seeking to the middle requires either downloading everything before it or complex range logic, and a viewer on a slow connection gets the same enormous file as one on fibre. The fix that the entire industry converged on: cut the video into small, independently-fetchable segments, and encode several quality versions of each.
8.2Segmentation, manifests, and adaptive bitrate#
The video is transcoded into a ladder of renditions — for example 240p at 400 kbps, 480p at 1 Mbps, 720p at 2.5 Mbps, 1080p at 5 Mbps, 4K at 15 Mbps — and each rendition is cut into segments of typically 2–10 seconds. A manifest file lists the renditions and their segment URLs.
Adaptive bitrate (ABR) is the client-side algorithm that exploits this. The player measures how fast recent segments arrived and how full its buffer is, and chooses the rendition for the next segment accordingly: buffer healthy and throughput high, step up a rung; buffer draining, step down immediately. The result the user perceives: playback starts fast at low quality and improves within seconds, and a network dip causes a visible quality drop instead of a stall. The trade-offs: shorter segments adapt faster and let playback start sooner, but multiply the request count and add per-segment overhead; longer segments compress slightly better and reduce request volume, but react sluggishly and increase startup delay. Two to six seconds is the usual compromise, with low-latency variants using shorter chunks.
The two formats. HLS (HTTP Live Streaming, from Apple) uses .m3u8 playlists and is universally supported, mandatory on iOS. MPEG-DASH is the open standard, codec-agnostic, using an XML manifest. They differ in packaging more than in concept, and CMAF exists precisely so one set of segment files can serve both, halving your storage and — more importantly — halving your cache footprint, since otherwise the CDN caches two copies of every segment.
Why this is ideal for a CDN: every segment is an immutable, cacheable file at a stable URL. Ten thousand viewers of the same live stream in one city request the same segment within seconds of each other, so one origin fetch serves all of them. The CDN's origin-offload ratio for popular video approaches 100%.
8.3Live streaming and its extra constraints#
Live adds a hard constraint absent from on-demand: glass-to-glass latency, the delay between the event happening and the viewer seeing it. Standard HLS/DASH with 6-second segments and a 3-segment buffer gives 20–30 seconds of latency — unacceptable for sports or auctions where a neighbour's cheer arrives before your picture. Low-Latency HLS and LL-DASH cut this to 2–5 seconds by delivering partial segments as they are encoded, using chunked transfer so the player begins consuming a segment before it is complete. Sub-second latency requires abandoning HTTP segments entirely for WebRTC, which trades CDN cacheability for interactivity.
The other live-specific problem is the origin thundering herd: at the instant a new segment becomes available, every edge in the world requests it simultaneously. The fixes are the ones you already know from File 02 §6.3: request coalescing at the edge (one origin fetch per PoP regardless of how many users are waiting), and an origin shield tier so that all PoPs collapse into a single origin request.
8.4Byte-range requests and large downloads#
For large non-video files (software updates, game patches, datasets), the mechanism is HTTP range requests: the client sends Range: bytes=1048576-2097151 and receives 206 Partial Content. This enables resumable downloads after an interruption, parallel fetching of several ranges at once to saturate a link, and seeking within a file.
The CDN consequence you must understand: a cache must decide whether to store the whole object on a range request or only the requested slice. Storing whole objects wastes bandwidth when clients only ever want fragments; storing slices fragments the cache and complicates invalidation. Real CDNs support both, typically by splitting large objects into fixed-size internal blocks and caching those independently — so a request for byte 5,000,000 fetches only the block containing it. The operational implication: your origin must correctly support range requests (many application servers do not, or do so incorrectly for dynamically-generated bodies), or large-file delivery degrades badly.
9Edge Compute#
Once a provider operates hundreds of PoPs with servers milliseconds from every user, running your code there is a small step — and it changes what the edge can do from "serve what I stored" to "decide, transform, and generate."
9.1The execution models, and why they differ#
- V8 isolates (Cloudflare Workers, Vercel Edge, Deno Deploy). Rather than a container per tenant, the runtime uses isolates — the same sandboxing mechanism a browser uses to separate one tab's JavaScript from another's. Thousands of tenants share one process, each in its own isolate. The consequence: cold start is effectively zero (single-digit milliseconds), and memory per tenant is tiny, which is what makes it economical to run code in hundreds of locations. The cost: you get a JavaScript/WASM runtime, not a machine — no arbitrary native binaries, no filesystem, no long-lived TCP listeners, and strict CPU-time limits per request (tens of milliseconds).
- Lightweight VMs / containers (AWS Lambda@Edge, Fastly Compute with WASM). More capability — more languages, longer execution, larger memory — at the cost of real cold starts and higher per-invocation cost. Lambda@Edge notably runs at regional edge caches rather than every PoP, so it is "closer than your origin" but not "as close as a Worker." CloudFront Functions is the contrasting lightweight tier: sub-millisecond, JavaScript-only, restricted to header and URL manipulation.
9.2What genuinely belongs at the edge#
- Request manipulation: rewriting URLs, normalizing cache keys (§5), adding security headers, redirecting by country or device, and A/B test bucketing — all of which are cheap, latency-sensitive, and would otherwise cost a full round trip to origin.
- Authentication and authorization checks: validating a JWT signature at the edge lets you reject an unauthenticated request in 10 ms instead of 200 ms, and keeps that traffic off your origin entirely.
- Personalization of otherwise-cacheable pages: fetch the cached shell, inject the user-specific fragment at the edge, and return one response — turning an uncacheable page into a mostly-cached one (§7).
- API aggregation: one client request fanning out to several origin services and being composed at the edge, so the user pays one long round trip rather than several.
- Serving directly from edge storage: the providers pair compute with edge key-value stores and object stores, so simple reads never touch your origin.
9.3What does not belong at the edge#
Anything requiring strongly consistent state. Edge state is by nature distributed across hundreds of locations, so it is eventually consistent unless the platform provides a specific coordination primitive (Cloudflare's Durable Objects exist precisely to give you a single-threaded, single-location object when you need serialization). The failure to avoid: implementing a counter, a lock, or an inventory decrement in edge storage and assuming it behaves like a database. It does not — you have reinvented multi-leader replication and its conflicts (File 08).
Also unsuited: long-running or CPU-heavy work (the limits are tight and the pricing punishes it), anything needing a large dependency tree, and anything requiring a private database connection your VPC would have to expose globally.
The general rule: the edge is for decisions and transformations on the request path, not for computation and state.
10Security at the Edge#
A CDN is a security product as much as a performance one, because a distributed edge is structurally capable of things a single origin can never be.
10.1DDoS absorption — why only an edge can do this#
A volumetric DDoS attack floods you with more traffic than your links can carry. Note carefully what that means: the defence is not clever filtering, it is capacity. If an attacker can generate 2 Tbps and your datacenter has 100 Gbps of connectivity, no firewall you install helps — your pipes are full before any software sees a packet. A major CDN operates hundreds of Tbps of aggregate capacity spread across hundreds of PoPs, and because it uses anycast (§4), the attack is automatically divided among all of those PoPs by the internet's own routing: traffic from a botnet in Brazil lands in São Paulo, traffic from Europe lands in Frankfurt, and no single location sees the whole flood. That structural property — the attack is split by the same mechanism that splits legitimate users — is the entire reason edge DDoS protection works and origin DDoS protection does not.
Attack classes, so you can distinguish them:
- Volumetric (L3/L4) — UDP floods, amplification attacks (DNS/NTP/memcached reflection, where a small spoofed query elicits a large response aimed at the victim). Absorbed by capacity and dropped at the edge.
- Protocol attacks — SYN floods that exhaust connection tables, handled with SYN cookies at the edge.
- Application-layer (L7) — plausible-looking HTTP requests aimed at expensive endpoints (search, login, cart). These are the hard ones because each request is individually legitimate; defences are rate limiting (File 03), bot detection, and challenges.
10.2WAF, bot management, and rate limiting#
The WAF (Web Application Firewall) inspects requests against rule sets — managed rules for known attack signatures (SQL injection, cross-site scripting, path traversal, and specific published CVEs) plus your custom rules. The trade-off you must state: rules can produce false positives that block real users, so the discipline is to deploy new rules in log-only mode first, review what would have been blocked, and only then enforce.
Bot management distinguishes automated traffic from human, using signals a simple IP block cannot: TLS fingerprints (JA3/JA4 — the ordering and set of parameters in the TLS handshake, which varies by client library and is much harder to forge than a user agent), HTTP/2 fingerprints, behavioural analysis, and reputation. Responses escalate: allow, challenge (a JavaScript proof-of-work or a CAPTCHA), throttle, or block. The nuance worth voicing: you want to block scrapers while allowing search-engine crawlers and your own monitoring, so bot management is always allow-listing plus classification, never a blanket rule.
Edge rate limiting is File 03's topic enforced at the cheapest possible place — see File 03 §8.1 for the mechanics and the accuracy trade-off of counting across PoPs.
10.3Origin protection — the step people forget#
All of the above is worthless if an attacker can bypass the CDN and hit your origin's IP directly, and origin IPs leak constantly (through DNS history, TLS certificate transparency logs, mail server records, or a subdomain that was never proxied). You must lock the origin so it only accepts traffic from the CDN. In increasing order of strength:
- Firewall to the CDN's published IP ranges. Simple, and it must be automated — those ranges change, and a stale allow-list becomes an outage.
- Shared-secret header. The edge adds a header with a secret value; the origin rejects requests without it. Cheap and effective.
- mTLS between edge and origin (File 01 §2.6), or a private tunnel from the origin outward (Cloudflare Tunnel, AWS PrivateLink) so the origin has no public inbound address at all. This is the strongest posture and increasingly the default recommendation.
10.4Protecting private content and the cache-poisoning class of bugs#
Signed URLs and signed cookies let a CDN serve private content without consulting your origin per request: you generate a URL containing an expiry and an HMAC signature over the path and expiry; the edge validates the signature with a shared key and serves or refuses. The trade-offs: a signed URL is bearer authority — anyone who obtains it within its validity window can use it, so keep expiries short — and you cannot revoke an issued URL before expiry without rotating keys.
Cache poisoning is the failure mode that turns a CDN into an attack amplifier: if an attacker can get a malicious response stored under a key that legitimate users will request, the CDN serves that response to everyone. The two common routes are unkeyed input (a request header influences the response but is not part of the cache key — the attacker sends a poisoned X-Forwarded-Host, the origin reflects it into the page, and the edge stores it under the ordinary URL) and cache deception (tricking the cache into storing a personalized page by requesting /account/settings.css, where the origin ignores the extension and serves the account page while the edge sees ".css" and caches it as a static asset). The defences: include in the cache key every input that can affect the response (or strip those inputs entirely), never let the origin reflect unvalidated headers, and configure caching by explicit Cache-Control from the origin rather than by file extension. This is the security face of the key-design rule in File 02 §2.7.
11Measuring a CDN#
You cannot manage what you do not measure, and CDN metrics have specific traps.
Cache hit ratio, measured at the right layer. The headline number is hits / (hits + misses), but a single figure hides the structure: the edge hit ratio is what determines user latency, while the origin offload ratio (the fraction of requests your origin never sees, counting shield hits) is what determines your origin bill and capacity. With a shield tier they differ substantially — an 85% edge hit ratio plus a shield absorbing most of the remainder can still mean 97% origin offload. Report both, and be suspicious of anyone quoting one without the other.
Two ratios also differ by unit: request hit ratio versus byte hit ratio. A CDN can hit on 95% of requests (all the small assets) while missing on the few large video segments that constitute most of the bytes. If you care about origin egress cost, the byte ratio is the one that matters.
Why the hit ratio is lower than you expect, and what to do: the usual causes are cache-key fragmentation from query strings and over-broad Vary (File 02 §7.4), TTLs that are too short, uncacheable Set-Cookie headers attached to static responses (many frameworks do this by default and it silently disables caching for those objects), and a long tail of rarely-requested objects that expire before they are requested twice. Diagnose by grouping hit ratio by path prefix and content type rather than looking at the global number.
Latency, measured where it matters. Edge-reported latency measures the edge's own service time and is flattering. Real User Monitoring (RUM) — instrumentation in the browser reporting actual timings from actual users — is the source of truth, because it includes DNS, connection setup, and the last-mile network that the CDN cannot see. Track it by geography and by percentile; a global p50 tells you nothing about the region where your CDN has poor presence, and the p99 is where the users who leave live.
Origin metrics as the control. Watch origin request rate, origin bandwidth, and origin error rate. A sudden rise in origin traffic with no traffic increase means your hit ratio has collapsed — usually because a deploy changed URLs, a header changed the cache key, or someone purged everything.
Cost metrics. CDN pricing is per-GB delivered plus per-request, varying by region (delivery in South America and Asia-Pacific commonly costs several times more than in North America or Europe). The number to compute is your effective cost per GB delivered and the origin egress avoided, since the whole financial argument for a CDN is that its per-GB rate is lower than your cloud provider's egress rate and that you serve far fewer bytes from origin.
12Pros, Cons & Trade-offs#
12.1Benefits#
- Latency: content served from ~20 ms away instead of ~200 ms — dramatic page-speed and video-startup wins.
- Origin offload & scalability: 90–99% of traffic absorbed by the edge; origin serves each object ~once.
- Bandwidth cost savings: far fewer origin egress bytes; CDN egress is cheaper at scale.
- Availability & resilience: edge keeps serving cached content (and
stale-if-error) even if the origin is down; anycast reroutes around dead PoPs. - Security: absorbs/filters DDoS (huge distributed capacity), integrates WAF/bot management/TLS at the edge.
- Protocol modernization: HTTP/3, TLS 1.3, compression at the edge regardless of origin.
12.2Costs & Trade-offs#
- Cache invalidation is hard (Phil Karlton, again) — stale content bugs; purge propagation delay; the fingerprinted-URL discipline is required.
- Cost & vendor lock-in: CDNs bill per GB + per request + per region; pricing is complex; migrating between CDNs is nontrivial.
- Cold cache / first-hit latency: the first user per object per PoP still pays the origin round trip (mitigated by shield/push/pre-warming).
- Not for truly private/dynamic-per-user data unless carefully scoped (
private, edge compute) — risk of caching one user's personalized/authenticated response and serving it to another (a serious security bug, see 9/10). - Debugging complexity: "which PoP served this? was it a hit? which TTL applied?" — needs cache-status headers and good observability.
- Consistency: eventual across PoPs; a purge isn't perfectly instant everywhere.
13Interview Diagnostic Framework (Symptom → Solution)#
| System Symptom | Why a CDN is the cure | Specific solution |
|---|---|---|
| "Users in Tokyo have 300 ms latency; US users are fine." | Distance latency; only fix is reducing distance. | CDN with an Asian PoP serving cached content locally. |
| "Our origin bandwidth/NIC is saturated serving images/video." | Origin can't serve the planet. | CDN edge caching (+ origin shield) offloads 90–99%. |
| "A viral post melts our origin every time." | Flash crowd hits origin. | CDN edge absorbs the spike; request collapsing + shield. |
| "Video buffers / slow to start for global users." | Segments fetched from far origin. | CDN caches HLS/DASH segments at the edge. |
| "We're getting volumetric DDoS'd." | Attack concentrates on origin. | Anycast CDN spreads/absorbs the attack; edge WAF. |
| "Deploys serve stale JS/CSS to some users." | Bad invalidation. | Fingerprinted (content-hash) filenames + long TTLs. |
| "We need to personalize but still want edge speed." | Dynamic seems uncacheable. | Micro-caching + ESI + edge compute (Workers). |
| "Cross-continent egress bill is huge." | Origin egress cost. | CDN offload reduces origin fetches + cheaper edge egress. |
14Real Implementations & Product Landscape#
"Put a CDN in front of it" names a category containing products with genuinely different architectures, strengths, and pricing models. This section is what you actually choose between.
14.1Family 1 — Full-service global CDNs#
Akamai. The oldest (founded 1998 out of MIT research on exactly the content-distribution problem this file describes) and still the largest by footprint, with servers in thousands of locations. Its distinguishing architectural choice is deep embedding: rather than a few large datacenters, Akamai places servers inside ISP networks, physically as close to end users as it is possible to get without being in their house. That is why it remains the choice for the largest media events and software distributions — when Apple ships an OS update to a billion devices, the last mile is the whole problem. It is also the most feature-dense platform (an enormous configuration surface, extensive security products, sophisticated media delivery).
- Best at: the absolute largest-scale delivery, reach into poorly-connected regions, and enterprise requirements with contractual guarantees.
- Limits: expensive, sold through enterprise contracts and sales cycles rather than a signup form, and its configuration model is complex enough to need specialists. Reach for it when you are a large media company or need reach where others are thin. Not when you want to be live this afternoon.
Cloudflare. Founded 2009, distinguished by running every service from every location — anycast (§4) across all PoPs, with DDoS protection, WAF, DNS, and Workers all executing at the same edge rather than in separate tiers. Its second distinguishing choice is commercial: an unusually capable free tier with unmetered DDoS protection and, notably, no charge for bandwidth on its CDN plans for standard web content — a direct attack on the industry's per-GB model. Workers (§9.1) is the most mature edge-compute platform, and R2 offers S3-compatible object storage with zero egress fees, which is strategically aimed at AWS's egress pricing.
- Best at: security-plus-performance in one product, edge compute, and cost predictability. Limits: the free and lower tiers have caveats around serving large volumes of non-HTML media, support quality scales with plan, and being a single vendor for DNS+CDN+security concentrates risk. Reach for it when you want strong defaults quickly and value DDoS/WAF integration.
Fastly. Founded 2011 around two design bets. First, instant purge: cache invalidation propagates globally in roughly 150 milliseconds, versus tens of seconds elsewhere — which changes what you can cache, because you can cache genuinely dynamic content (a news homepage, a stock page, an inventory count) and purge it the instant it changes, rather than choosing a short TTL. Second, programmability: originally VCL (the Varnish Configuration Language — see File 02 §10.3) and now Compute running WebAssembly, letting you express complex caching and routing logic as code. Fastly deliberately runs fewer but larger PoPs than Akamai, betting that well-connected large nodes beat many small ones.
- Best at: dynamic content caching with surrogate-key purging, and engineering teams who want to program the edge. Limits: smaller PoP count means weaker presence in some regions; the developer-centric model expects you to write configuration rather than click it.
AWS CloudFront. The default when you are already on AWS, and its argument is integration rather than raw superiority: origin access control to S3 buckets that are otherwise fully private, native ACM certificates, WAF and Shield integration, Lambda@Edge and CloudFront Functions (§9.1), and Origin Shield as a configurable mid-tier. Its most important commercial property: data transfer from S3 (or EC2) to CloudFront is free, and CloudFront's own egress rates are lower than direct S3 egress — so putting CloudFront in front of S3 frequently reduces your bill rather than adding to it. Limits: configuration changes historically propagate slowly; invalidations are slower and charged beyond a free allowance (the standard workaround is versioned object names, §5); and it is less compelling if your origin is not on AWS.
Google Cloud CDN and Media CDN ride Google's private backbone with a single global anycast IP, tightly coupled to Google Cloud Load Balancing; Media CDN is the separate product built on the YouTube delivery infrastructure for large-scale video. Azure Front Door occupies the same position for Azure, combining global load balancing, CDN, and WAF.
14.2Family 2 — Value and specialist providers#
BunnyCDN competes on price and simplicity with per-GB rates a fraction of the enterprise providers', plus a straightforward video-streaming product. Best at: cost-sensitive projects with ordinary requirements. Limits: fewer enterprise features and less security depth.
Cloudflare R2, Backblaze B2, and Wasabi are storage rather than CDN, but they belong in this discussion because egress pricing is often the dominant cost in a content-delivery architecture. R2 charges zero for egress; B2 and Wasabi charge little or nothing under fair-use terms; S3 charges meaningfully per GB. Pairing cheap-egress storage with a CDN is one of the highest-leverage cost decisions available, and the Bandwidth Alliance exists precisely so that traffic between member storage providers and member CDNs is not double-billed.
14.3Family 3 — Private and purpose-built CDNs#
Netflix Open Connect is the canonical example of building rather than buying, and it is worth understanding as an architecture. Netflix places its own hardware appliances — Open Connect Appliances, essentially dense storage servers — directly inside ISP networks and at internet exchanges, given to ISPs at no cost because it saves the ISP transit bandwidth. Content is pushed (§ the push-vs-pull discussion earlier) during off-peak hours, using Netflix's own prediction of what will be watched in that region tomorrow, so at peak time the content is already there and the stream never crosses the wider internet. Why this is only right for Netflix: it requires a catalogue small enough to preposition, viewing patterns predictable enough to forecast, volume large enough to justify hardware, and the organizational capacity to run a global hardware fleet. The takeaway to state in an interview: build your own CDN only when your traffic is a large fraction of the internet's and your content is predictable; otherwise the economics are ruinous.
Meta, Google, and Apple operate comparable private edge networks for the same reasons.
14.4Family 4 — Framework and platform edges#
Vercel, Netlify, Deno Deploy, and Cloudflare Pages bundle a CDN with a deployment platform: you push code, and static assets are distributed to the edge while server-rendered routes execute at edge or regional functions. Best at: developer velocity for web applications, with caching configured largely by convention. Limits: you inherit their CDN choices, cost scales differently (per-invocation and per-seat rather than purely per-GB), and heavy media delivery is usually not the sweet spot. Note the layering honestly: several of these run on top of the providers above, so you are choosing a developer experience, not an independent network.
14.5Adjacent products people confuse with CDNs#
AWS Global Accelerator provides anycast IPs and routes traffic over AWS's backbone to your regional endpoints — it delivers the routing and TCP termination benefits of §7 but does not cache anything. It is the right answer for accelerating non-HTTP protocols or a stateful TCP/UDP service; it is the wrong answer if you wanted caching. Confusing these two is a common interview error.
DNS-based global traffic managers (Route 53 latency/geolocation routing, NS1, Akamai GTM) steer users to regions at resolution time with no data path at all — see File 01 §9.4 for why TTL caching makes this a coarse instrument.
Image and video CDNs (Cloudinary, imgix, Mux) are specialist layers combining transformation with delivery, worth naming when the media pipeline itself is the problem rather than the distribution.
14.6Comparison table#
| Provider | PoP model | Purge speed | Edge compute | Security depth | Pricing shape | Best for |
|---|---|---|---|---|---|---|
| Akamai | Thousands, embedded in ISPs | Seconds | EdgeWorkers | Very deep | Enterprise contract, $$$$ | Largest-scale media & software delivery |
| Cloudflare | Hundreds, all services everywhere | Seconds (instant with tags) | Workers (V8 isolates, best-in-class) | Very deep, unmetered DDoS | Free tier; plan-based, bandwidth-inclusive | Security + performance + edge compute |
| Fastly | Fewer, larger, well-peered | ~150 ms global | Compute (WASM) | Strong (WAF, bot) | Per-GB + per-request | Dynamic caching, programmable edge |
| CloudFront | Hundreds + regional edge caches | Slower, charged past free tier | Lambda@Edge, CloudFront Functions | WAF + Shield | Per-GB (free from S3/EC2) | AWS-native stacks |
| Google Cloud CDN / Media CDN | Google backbone, single anycast IP | Fast | Cloud Run/Functions adjacency | Cloud Armor | Per-GB | GCP stacks; large-scale video |
| Azure Front Door | Microsoft edge | Fast | Rules engine | WAF integrated | Per-GB + routing rules | Azure stacks |
| BunnyCDN | Broad, low-cost | Fast | Edge scripting | Basic | Very low per-GB | Cost-sensitive standard delivery |
| Netflix Open Connect | Appliances inside ISPs | n/a (push) | n/a | n/a | Own hardware | Only if you are Netflix-scale |
| Vercel / Netlify | Rides other networks | Deploy-triggered | Edge functions | Basic | Per-seat + usage | Web app developer velocity |
| Global Accelerator | AWS anycast, no cache | n/a | ❌ | Shield | Hourly + per-GB | Non-HTTP acceleration, static IPs |
14.7Decision rules#
- Choose Cloudflare when you want strong security and performance defaults immediately, predictable cost, or the best edge-compute platform — and especially when DDoS protection is a stated requirement rather than an afterthought.
- Choose Fastly when your content is dynamic and your advantage comes from caching it aggressively and purging it precisely — news, e-commerce, anything where "cache it for 60 seconds" was a compromise you disliked. Its instant purge is the feature you are actually buying.
- Choose CloudFront when your origin is S3 or AWS compute: the free origin transfer and private-bucket integration usually make it both cheapest and simplest, and cross-cloud egress fees would punish any other choice.
- Choose Akamai when your requirements are reach and scale beyond what the others cover, or when enterprise contractual guarantees are part of the purchase.
- Choose a value provider (Bunny) when requirements are ordinary and per-GB cost dominates — but price the security features you are giving up rather than assuming you do not need them.
- Choose to build (Open Connect style) essentially never, unless your traffic is a measurable fraction of global internet volume and your content is predictable enough to preposition.
- Choose Global Accelerator, not a CDN, when the protocol is not HTTP or you need static anycast IPs without caching.
- Multi-CDN is a real strategy for the largest deployments — steering traffic between two providers by measured performance, with automatic failover if one degrades. The cost is real: you must configure and validate caching semantics twice, your hit ratio splits across two caches, purges must fan out to both, and you need a steering layer. Reach for it when availability requirements exceed what one provider's SLA gives you, or when regional performance differences are large enough to measure.
14.8Anti-recommendations#
- Assuming a CDN only serves static files. Section 7 is the counter-argument: even a fully uncacheable API benefits from edge TLS termination, warm origin connections, slow-start avoidance, and backbone routing.
- Caching a personalized page on a shared edge. The single most damaging CDN misconfiguration there is — one user's account page served to thousands. Mark it
private, and put every varying input into the cache key (§10.4, File 02 §7.4). - Leaving the origin publicly reachable. Your WAF and DDoS protection are decorative if attackers can address the origin directly (§10.3).
- Purging everything to fix one object. A full purge is a self-inflicted origin stampede (File 02 §6.2). Use surrogate keys or versioned URLs.
- Treating an invalidation as instant everywhere. Propagation time varies by provider from milliseconds to tens of seconds, and browser caches you already served cannot be purged at all.
- Ignoring egress pricing when choosing storage. The CDN bill is often the smaller half; origin egress from a cloud provider at per-GB rates can dominate, and the fix is a storage choice, not a CDN choice (§14.2).
- Enabling 0-RTT for state-changing requests. Replayable by design (§6.1).
15Real-World Engineering Scenarios#
15.1Netflix — Open Connect (a purpose-built CDN)#
Netflix is ~15% of global internet traffic at peak; a generic CDN couldn't do it economically, so they built Open Connect:
- Netflix ships Open Connect Appliances (OCAs) — their own caching servers — and places them inside ISP networks and at IXPs, as close to viewers as physically possible (often in the subscriber's own ISP).
- During off-peak hours, Netflix proactively pushes (predictive fill) the next day's likely-popular titles to the OCAs — a push CDN using their recommendation data to pre-position content. So when you hit play, the video streams from a box inside your ISP — minimal latency, zero long-haul.
- The control plane (which OCA should serve you) uses health/proximity/capacity steering (GSLB-style); the video segments are the cached objects.
- Takeaway: at extreme scale you push content predictively to edges inside ISPs; separate the control plane (routing) from the data plane (segment serving).
15.2Cloudflare — Anycast Everything#
Cloudflare fronts a huge fraction of the web:
- Every Cloudflare IP is anycast — announced from all ~300+ PoPs. A user's request lands at the nearest PoP purely via BGP, no GeoDNS needed.
- Anycast gives them industry-leading DDoS absorption: a volumetric attack against a customer's anycast IP is automatically spread across every PoP's capacity, diluting it.
- At the edge they run Workers (edge compute) for auth, redirects, personalization, and even full apps, plus WAF and bot management — all executing near the user, not at origin.
- They use tiered caching / origin shield so edge misses funnel through a parent cache before hitting the customer origin.
- Takeaway: anycast is the routing backbone; edge compute + tiered caching turn the CDN into a global application platform.
15.3Amazon CloudFront + S3 — The Canonical Static Site / Asset Stack#
- Static assets — or a whole SPA (Single-Page Application: a web app delivered as one HTML shell plus JS bundles that render everything client-side and talk to APIs, so the entire UI is static files, perfectly cacheable) — live in an S3 bucket (the origin — File 09 territory). CloudFront (pull CDN) sits in front.
- Route 53 (DNS/GSLB) with latency-based routing + CloudFront's own edge network route users to the nearest of hundreds of edge locations. TLS (ACM cert) terminates at the edge.
- Assets use **content-hashed filenames +
Cache-Control: max-age=31536000, immutable; the HTML has a short TTL. Deploys upload new hashed files and update HTML → instant, invalidation-free cache-busting. Origin Shield** (a regional edge cache) is enabled to minimize S3 GET requests. - On a purge need, CloudFront invalidation clears specific paths.
- Takeaway: the standard cloud pattern — object storage origin + pull CDN + DNS-based geo routing + fingerprinted immutable assets + origin shield.
16Interview Gotchas & Failure Modes#
16.1Classic Questions#
- "How does a user get routed to the nearest edge?" — Anycast (BGP delivers to the topologically nearest PoP announcing a shared IP) and/or DNS-based GeoDNS/GSLB (authoritative DNS returns the best PoP by geo/latency/load/health). Compare their trade-offs (failover speed, DDoS, granularity).
- "Push vs pull CDN?" — Pull = lazy fill on first miss (default, simple); push = pre-upload known-popular content (control, avoids first-hit penalty). Netflix pushes; most web uses pull.
- "How do you cache dynamic content?" — Micro-caching (1–5s TTL), ESI/fragment caching, stale-while-revalidate, edge compute for personalization.
- "How do you invalidate/version content?" — Prefer fingerprinted immutable URLs (no invalidation needed); otherwise purge by URL or surrogate-key/tag; avoid purge-all (origin miss storm).
- "What's an origin shield and why?" — A mid-tier cache that funnels all edge misses through one point + request collapsing, so the origin sees ~1 fetch instead of hundreds. Prevents origin thundering-herd.
- "Anycast vs GeoDNS?" — See the 4.4 table; know that anycast excels at DDoS/failover, GeoDNS excels at load/health/policy granularity, and real CDNs combine them.
16.2Failure Modes & Mitigations#
- Serving stale content after a change → bad TTL/invalidation. Mitigate: fingerprinted URLs, correct
Cache-Control,ETagrevalidation, targeted purges. - ⚠️ Caching private/personalized data and serving it to the wrong user → a serious security incident (leaking one user's authenticated page to another). Mitigate:
Cache-Control: private/no-storeon personalized responses, never cache with auth cookies unless deliberately scoped, carefulVary, review edge cache keys. (A famous class of real-world CDN misconfig bugs.) - Cache poisoning → an attacker gets a malicious response cached and served to others (often via unkeyed headers). Mitigate: careful cache-key/
Varyconfig, ignore untrusted headers in the key. - Purge-all miss storm → global purge sends every request to the origin at once (self-inflicted avalanche, File 02). Mitigate: purge narrowly (URL/tag), pre-warm, keep origin shield + request collapsing.
- Cold PoP / first-hit latency → the first user per object per PoP pays the origin trip. Mitigate: origin shield, push/pre-warm popular content.
- Origin down → misses can't be filled. Mitigate:
stale-if-error(serve stale during origin outage), longer TTLs, multi-origin failover. - PoP outage → users on that PoP affected. Mitigate: anycast auto-reroutes; GeoDNS health checks steer away (bounded by DNS TTL).
- **Cache fragmentation from over-
Vary** → too many variants → low hit ratio → high origin load. Mitigate: minimizeVarydimensions; normalize headers/query strings in the cache key. - **
Vary/query-string cache-key mistakes** → identical content cached many times (or wrong content shared). Mitigate: strip irrelevant query params from the key.
17Whiteboard Cheat Sheet#
Users (worldwide)
│ DNS/Anycast picks NEAREST PoP (GSLB: geo+latency+load+health, or BGP anycast)
▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ... hundreds of PoPs (edge servers)
│ PoP Tokyo│ │PoP London│ │PoP Sydney│ each = cache + TLS term + WAF + edge compute
└────┬────┘ └────┬────┘ └────┬────┘
│ miss │ miss │ miss
└────────────┴──── ORIGIN SHIELD (mid-tier cache, request collapsing) ────┐
▼
┌──────────────┐
│ ORIGIN │ served ~once
│ (S3 / backend)│ per object/region
└──────────────┘
ROUTING: Anycast (BGP -> nearest, great DDoS/failover, coarse)
GeoDNS/GSLB (DNS -> best PoP by geo/load/health, fine control, DNS-TTL lag)
FILL: Pull (lazy on first miss, default) | Push (pre-position known-popular, e.g. Netflix)
CACHE-CTRL: max-age/s-maxage, ETag(304 revalidate), immutable + content-hash filenames (cache-bust)
DYNAMIC: micro-cache(1-5s) | ESI fragments | stale-while-revalidate / stale-if-error | edge compute
OFFLOAD: origin shield + request collapsing => origin sees ~1 fetch, not N PoPs
DANGER: never cache private/auth responses publicly (Cache-Control: private/no-store)One-sentence summary for an interviewer:
"A CDN is a globally distributed cache that beats the speed-of-light latency floor by serving content from an edge PoP near the user and offloads 90–99% of traffic from the origin; users reach the nearest edge via anycast (BGP) and/or GeoDNS/GSLB (policy-aware), content is filled pull (lazy) or push (pre-positioned like Netflix), an origin shield collapses misses so the origin is fetched ~once, static assets use fingerprinted immutable URLs to sidestep invalidation, and you must never publicly cache private/authenticated responses."
End of File 05. Next → File 06: Consistent Hashing (hash rings, virtual nodes, minimal rehashing) — the algorithm we've foreshadowed in Files 01, 03, and 04.