5 min read

CDN

A network of caches near your users that absorbs most of your traffic, if you tell it exactly what's safe to cache.


The story

On Christmas Day 2015, Steam, Valve's game store, was hit by a large traffic flood. In response, a caching configuration change was rolled out. The new configuration cached pages that should never have been cached: account pages, with personal details on them.

For roughly an hour and a half, some users who opened their account page were served someone else's cached page instead. Valve later said around 34,000 users' information may have been shown to others: billing and email addresses, purchase history, and the last digits of card numbers.

The CDN worked exactly as configured. It took a response and served it again to the next person who asked for the same URL. That's what makes a CDN fast, and it's also what makes a wrong cache rule a privacy incident.

A CDN is the cheapest scaling win available. This page is about getting that win and keeping private data out of the cache.


The idea

A CDN is a fleet of caching servers in hundreds of locations (points of presence, or PoPs) close to users. Users connect to the nearest PoP. If it has the response, it's served from there, and your origin never sees the request.

What you get:

  • Latency: bytes and the TLS handshake travel tens of kilometres, not thousands (Data Locality).
  • Offload: with a 95% hit ratio, the origin serves 1 in 20 requests. The 9 GB/s of thumbnails in Estimation becomes about 450 MB/s at the origin.
  • Protection: the CDN's capacity absorbs DDoS floods, and WAF rules run at the edge.
  • Origin shield: a middle tier, so a miss in 200 PoPs becomes one request to your origin, not 200.

Pull vs push. Almost everyone uses pull: the edge fetches from the origin on the first miss and caches it. Push (you upload content to the CDN in advance) suits large files you know will be requested, such as a game patch or a video release.


The cache key and the private-data rule

The CDN serves a cached response to any request with the same cache key, by default the URL (host + path + query string). Anything not in the key is ignored. That includes the cookie that says who the user is.

Defensive rules that would have prevented the story:

  • The origin marks every personalised response private or no-store. Don't rely on the CDN's path rules alone.
  • Default to not caching paths that have a session cookie or an Authorization header unless they're explicitly marked public.
  • Put personalised data in API calls the page makes after it loads (cached nowhere), and cache the page shell.

Freshness and invalidation

  • Static assets: fingerprint the filename and cache for a year. Deploys change the URL, so nothing ever needs purging.
  • HTML and API responses: short s-maxage (the shared-cache TTL) plus stale-while-revalidate, so users get an instant answer while the edge refreshes.
  • Purges: by URL or by surrogate key/tag (e.g. purge everything tagged product-42). Good for "the price was wrong". Bad as the only invalidation strategy.

Beyond caching: CDNs also speed up uncacheable requests (TLS terminates near the user, and the CDN keeps warm connections to your origin), and run code at the edge (Cloudflare Workers, Lambda@Edge) for redirects, A/B splits and auth checks.


Cheat sheet

QuestionAnswer
What to put on a CDNAll static assets, media, public pages and public API responses
Never at the edgeAnything that differs per user: Cache-Control: private / no-store
Cache keyURL + only the headers that really vary the response (language, device)
Static asset TTL1 year + fingerprinted filenames
Dynamic but publicShort s-maxage + stale-while-revalidate
Fix a wrong response nowPurge by URL or surrogate key
Many PoPs missing at onceOrigin shield
Healthy hit ratio90%+ for static content. Track it per path.
Big planned releasePre-warm or push to the CDN
BonusDDoS absorption, WAF, edge TLS, edge compute

Say it in the interview

"Everything static goes through the CDN with fingerprinted filenames and a one-year TTL. Public product pages get a 60-second s-maxage with stale-while-revalidate, and price changes purge by product tag. Anything personalised is marked private at the origin, so even a bad CDN rule can't cache it. An origin shield keeps misses from 200 PoPs down to one request to us."


Go deeper