Content Delivery Networks (CDNs)
A request that has to cross an ocean pays for it. The speed of light is not negotiable: a round trip from Sydney to Virginia is well over 200 ms before your server does any work at all. No amount of faster code fixes distance. The only fix is to move the content closer to the user — and that is exactly what a Content Delivery Network does. A CDN is a globally distributed fleet of caching servers (“edge” or PoP — Points of Presence) placed in hundreds of cities, so the answer is fetched from a machine a few milliseconds away instead of one a continent away.
A CDN is best understood not as a new primitive but as a composition of two blocks you already know: caching plus DNS/anycast routing. It’s a cache hierarchy whose outermost layer has been scattered across the planet, with DNS/anycast steering each user to the nearest edge.
What does a CDN buy us, and what does it cost? It buys dramatically lower latency for distant users and massive origin offload (most requests never reach your servers). It costs you staleness at the edge, a harder invalidation problem (now spread across hundreds of locations), and operational complexity — plus a bill.
How a request reaches the edge
Section titled “How a request reaches the edge” User in Tokyo ──► CDN edge in Tokyo │ cache HIT ──► served in ~5 ms, origin never touched │ │ cache MISS ──► fetch from origin (maybe via a regional ▼ parent cache), store it, then serve. Origin (your servers, one region) — touched rarelyAnycast or GeoDNS routes the user to a nearby edge. If the edge has the content, it serves it immediately. If not, it fetches from your origin (or an intermediate “parent” cache), stores a copy, and serves it — so the next nearby user gets a hit. The first miss pays the long-distance cost; everyone after rides the local copy.
Push vs pull: how content gets to the edge
Section titled “Push vs pull: how content gets to the edge”There are two ways the edge comes to hold your content:
| Pull CDN | Push CDN | |
|---|---|---|
| How | edge fetches from origin on first miss (lazy) | you upload content to the CDN ahead of time |
| Effort | minimal — just set caching headers | you manage what’s where and when |
| First request | pays a miss penalty | already warm |
| Best for | large, mostly-read catalogs (most sites) | a few large files, predictable demand (software releases, video) |
Pull is the default and the simplest: you do nothing special, the edge populates itself on demand based on real traffic, and rarely-requested content never wastes edge storage. The cost is that the first user in each region eats a cache miss. Push front-loads the work — you proactively place content so the first request is already fast — which is worth it when you know exactly what will be hot (a game patch dropping to millions at once) and don’t want any cold-start misses.
Static vs dynamic content
Section titled “Static vs dynamic content”CDNs were born for static content — images, CSS, JavaScript, fonts, video segments — that is identical for every user and changes rarely. This is the perfect cache fit: high reuse, long freshness windows, no personalization.
Dynamic content (a personalized feed, a logged-in dashboard) is the hard case, because it differs per user and changes constantly — there’s nothing to share across requests. Modern CDNs attack this from several angles:
- Cache cacheable dynamic content briefly (micro-caching) — even a 1-second TTL on a hot, public page can absorb a huge spike, because thousands of requests in that second collapse to one origin fetch.
- Edge compute — run logic at the edge (edge functions/workers) so personalization and assembly happen near the user instead of at a far origin.
- Dynamic acceleration — even uncacheable requests benefit, because the CDN routes them over optimized, pre-warmed backbone connections from the nearby edge to your origin, beating the public internet’s path.
The honest line: a CDN’s biggest win is always on cacheable content. Dynamic acceleration helps, but it can’t repeal the speed of light for a request that genuinely must reach your origin and back.
Cache invalidation at the edge
Section titled “Cache invalidation at the edge”The staleness problem from the caching page gets harder with a CDN, because your cached copies now live in hundreds of locations you don’t directly control. Three tools manage it:
- TTL / expiry headers — the default. Content is trusted for N seconds, then revalidated. Simple, but you can’t pull back a copy early.
- Purge / invalidation — explicitly tell the CDN to drop an object everywhere now. Effective but global purges can be slow to fully propagate, and aggressive purging defeats the point of the cache.
- Versioned URLs (cache busting) — the cleanest pattern: never invalidate; instead change the
name. Ship
app.a1b2c3.jsinstead ofapp.js, so a new version is a new URL with no cached copy anywhere, while old URLs can keep their long TTLs harmlessly.
When a CDN isn’t the answer
Section titled “When a CDN isn’t the answer”CDNs shine for read-heavy, cacheable, globally-distributed traffic. They do little for a write-heavy internal API with no reuse, and they add cost and a dependency you must operate. As always, weigh the buy (latency, offload) against the cost (staleness, invalidation, complexity) for your traffic shape — not in the abstract.
Check your understanding
Section titled “Check your understanding”- Why is a CDN best described as a composition of caching and DNS/anycast rather than a new primitive?
- Contrast push and pull CDNs. Which one makes the first user in a region pay a penalty, and when is push worth the extra effort?
- Why is dynamic, personalized content the hard case for a CDN? How does micro-caching still help a public dynamic page under a spike?
- Explain why “long TTL + versioned URLs” lets you have maximal caching and instant updates at once.
- Describe a way a CDN can amplify a mistake, and one configuration choice that prevents leaking one user’s data to another.