CDNs
Serve static files and media from servers near your users: edge caching, push vs pull, cache keys, invalidation, signed URLs and what belongs on a CDN.
On this page
A shop serves product images from one region. At peak, pages pull 5,000 images a second at about 200 KB each: 5,000 × 200 KB = 1 GB/s, or 8 Gbit/s, all leaving one set of servers. Users 8,000 km away wait at least 80 ms per round trip for every image, though the images are the same for every shopper.
The idea
A content delivery network (CDN) is a set of caching servers, called edges, in many cities. Users reach a nearby edge. If it has the file, it answers; if not, it fetches the file once from your servers (the origin) and keeps a copy for everyone after.
Latency: an edge 500 km away is 2 × 500 ÷ 200 = 5 ms per round trip instead of 80 (from Networking Essentials, light in fibre covers about 200 km per ms). Load: if edges answer 95% of requests, the origin sends 1 GB/s × 0.05 = 50 MB/s instead of 1 GB/s.
The cost is the cost of any cache: copies in hundreds of places that you cannot update instantly.
A file's life on a pull CDN
- origin requests
- 0
1A shopper in Paris asks for
/img/p42.jpg. DNS or anycast routing sends her to the Paris edge, a few milliseconds away.- origin requests
- 1
2The edge has never seen this file: a miss. It fetches it from the origin, paying the long round trip once.
- origin requests
- 1
3The origin replies with
Cache-Control: max-age=86400. The edge keeps the image for a day and sends it to the shopper.- origin requests
- 1
4The next shopper in Paris gets a hit in about 5 ms. The origin never hears about it.
- origin requests
- 2
5A shopper in Seoul asks for the same file. Edges do not share caches, so the Seoul edge misses and goes to the origin too.
- origin requests
- 2
6The team uploads a new photo under the same name. The Paris edge keeps serving the old one until its 24 hours run out.
- origin requests
- 3
7The fix: the page now links to
/img/p42.v2.jpg. A new name is a new cache key, so every edge misses once and fetches the new photo.- origin requests
- 3
8The origin goes down. Edges keep serving every cached file, so most images still load. Misses fail, unless the CDN is set to serve an expired copy on error.
Step 5 shows why hit rates are lower than you expect: every edge fills its own cache. Many CDNs add an origin shield, one middle cache that all edges ask before the origin, so the origin sees one miss per file instead of one per edge.
Push or pull
| Option | Good at | Bad at | Pick it when |
|---|---|---|---|
| Pull Usual default | Nothing to manage: edges fetch on first request and drop files nobody asks for. | The first request at each edge is slow, and a big launch sends a burst of misses to the origin. | Almost always: images, scripts, styles, video segments. |
| Push | Files are in place before anyone asks, and the origin never sees a miss storm. | You upload and delete files yourself and pay to store them everywhere, popular or not. | Large files with a known release moment: a game patch, a video premiere. |
Cache keys and invalidation
The cache key decides which requests share a copy. By default it is roughly the host, path and query string. Too much in the key and the hit rate collapses: if ?utm_source=mail is part of the key, every campaign link stores its own copy of the same image. Too little and users see the wrong content: if the key ignores the ?size=small that changes the response, everyone gets whichever size was cached first. Keep only the parts that change the bytes.
Three ways to change a cached file, best first:
- Versioned names. Put a version or a content hash in the file name (
app.3f9a1c.js) and cache it for a year. A new version is a new URL, so nothing needs purging. Keep the HTML that points to it on a short TTL. - TTL. Let copies expire. Simple, but users may see old content for the whole TTL.
- Purge. Ask the CDN to drop a path from every edge. It takes time to reach every edge, and then every edge misses at once.
Signed URLs for private files
Paid videos and private documents still belong on a CDN, but only the right people should fetch them. A signed URL carries an expiry time and a signature over the path and expiry, often a keyed hash (HMAC) made with a secret that your app and the CDN share. The edge checks the signature and the time on its own, without calling your servers.
https://cdn.example.com/videos/v881/seg-0042.ts
?expires=1767225600
&sig=HMAC(secret, "/videos/v881/seg-0042.ts" + "1767225600")Anyone holding the URL can use it until it expires, so keep expiry short: minutes, not days. For a video made of hundreds of segments, a signed cookie covering the folder saves signing each one.
What to put on a CDN
- Yes: images, scripts, styles, fonts, video segments, downloads, and public responses that are the same for everyone, even with a TTL of a few seconds (a live score).
- With signed URLs: paid or private media.
- No: pages that differ per user, and anything that must be up to the second for every reader.
Uncached requests still gain from a CDN: users handshake with a nearby edge, which keeps warm connections to your origin.
Numbers worth remembering
- Origin load = total requests × (1 − hit rate). Going from 90% to 99% hits cuts it tenfold.
- Video bandwidth: viewers × bitrate. Remember 8 bits per byte.
How much bandwidth must the origin serve for this stream?
- 20,000 viewers watching at once
- 5 Mbit/s per viewer
- The CDN serves 98% of the bytes from edges
Show the working
- Total: 20,000 × 5 Mbit/s = 100,000 Mbit/s = 100 Gbit/s
- Origin share: 100 Gbit/s × 0.02 = 2 Gbit/s
- In bytes: 2 Gbit/s ÷ 8 = 250 MB/s
Estimate 250 MB/s (anything from 80 MB/s to 1 GB/s is a good answer)
Without the CDN: 100 Gbit/s. For live video each edge fetches each segment about once, so origin load follows the number of edges, not viewers.
In the interview
Bring a CDN in whenever there are static files, media, or users spread across regions. Say what goes on it and how it is invalidated: "Images and video segments are identical for every user and most of our bytes, so they go on a CDN. File names carry a content hash, so I cache them for a year and never purge. HTML gets a short TTL."
Videos are for paying subscribers only. Can they still go on a CDN?
Yes. The app checks the subscription and hands out a signed URL or signed cookie that expires in a few minutes. Edges verify the signature themselves, so the origin only sees misses.
What if someone shares the URL?
It works for anyone until it expires, which is why expiry is short. If sharing is a real threat, I'd sign the viewer's IP address in too, so the URL fails on other networks.
Follow-ups to expect:
- "How does a user reach the nearest edge?" DNS that answers by the resolver's location, or anycast: one IP announced from many places, so the network routes to the closest.
- "What if the CDN goes down?" Fail over to a second CDN by DNS, or to the origin, which must then survive 100% of the traffic. Usually it cannot, so a second CDN is the real plan.
- "Why is the hit rate low?" Too many cache keys (tracking parameters, cookies), short TTLs, or a long tail of files spread over many edges. An origin shield helps the last one.
Common mistakes
An origin serves 2,000 image requests a second through a CDN. The hit rate rises from 90% to 99%. How many requests a second reach the origin now?
A new version of app.js is deployed under the same name, cached for a day. Users report the old behaviour for hours. What is the best lasting fix?
A software update is 2 GB and goes live for millions of users at 10:00. Push or pull?
What to practise next
CDNs handle data that flows one way and changes rarely. For data that must reach users the moment it changes, read Realtime Communication. To see a CDN carry most of a system's bytes, work through Design Video Streaming.