Ctrl K
Lesson

CDN and Static Content

Intuition: a local pickup point instead of a central warehouse

Picture an online store with one giant warehouse outside Chicago. If every order from Seattle shipped from there, a package would take a week and the warehouse would be swamped. So popular products get shipped ahead of time to pickup points near the customers. You grab your package around the corner, and the central warehouse handles the rare orders.

A CDN (Content Delivery Network) works the same way. It's a network of edge servers (edge, PoP) around the world. They hold copies of your files: JS, CSS, images, video. The user gets the file from the nearest node, and your main server (the origin) only responds when the edge doesn't have a copy.

Why static content is served from the edge

Static content is files that are the same for everyone: logo.png, app.js, video thumbnails. It's ideal for caching, and that pays off in three ways:

  • Latency. You can't speed up the speed of light. The RTT from Sydney to a server in Virginia is about 200 ms; to a CDN node in Sydney, about 10 ms. TCP + TLS take 2–3 RTTs before the first byte even arrives. So the difference is hundreds of milliseconds on every connection.
  • Load on the origin. The edge handles most requests, and only a small share reaches you.
  • Bandwidth and resilience. Traffic spikes (a launch, a viral image) and even DDoS attacks land on a huge distributed network instead of your three servers.

Diagram

HTTPSHTTPSmiss: staticmiss: staticAPI requestsUser (London)clientUser (Tokyo)clientCDN edge: LondonCDNCDN edge: TokyoCDNObject storage (S3)storageAPI (origin for dynamic content)servicePostgreSQLDB
Static files and media are served from the edge; only cache misses and dynamic requests go to the origin

How the edge cache works

  1. The user requests cdn.site.com/app.3f9a2c.js. DNS or anycast routes them to the nearest node.
  2. Cache hit: the file is there and hasn't expired, so the node serves it right away.
  3. Cache miss: the node goes to the origin (S3, for example), stores a copy, and serves it. The next users in that region get a hit.

How long a copy is kept is decided by the TTL. The origin usually sets it with headers:

HTTP/1.1 200 OK
Content-Type: application/javascript
Cache-Control: public, max-age=31536000, immutable
ETag: "3f9a2c"

max-age=31536000 means "keep it for a year," and immutable means "don't even bother revalidating." HTML gets a short TTL or no-cache so users see the new version of a page quickly.

Invalidation: the version in the file name

The big headache with caching is how to update a file that's already spread across a hundred nodes with a one-year TTL. There are two ways:

Approach How it works Downsides
Purge via the CDN API "Delete /app.js on every node" Slow (seconds to minutes), often paid, and browsers keep their own copy anyway
Version in the name app.3f9a2c.js, where the hash comes from the file contents You need a build step that rewrites the links in the HTML

The second approach is the industry standard. A file with a given hash never changes, so it can be cached forever. A new release produces a new name (app.8b1d07.js), the HTML starts pointing to it, and the old copy simply stops being requested. Nothing needs invalidating: only the HTML needs a short TTL.

index.html (TTL 60 s)→app.8b1d07.js (TTL 1 year)→style.a1c4e2.css (TTL 1 year)→null
Only the entry point needs a short TTL; everything else is versioned

Tip: in an interview, put it like this: "We version static files with a hash in the name and cache them as immutable for a year, while HTML is served with a short TTL. Purge is for emergencies."

Let's count the savings

Say there are 10 million page views a day with 2 MB of static content each, and a 95% CDN hit rate.

Quantity Calculation Result
Daily traffic 10M × 2 MB 20 TB
Average bandwidth 20 TB / 86,400 s ≈ 230 MB/s ≈ 1.9 Gbps
Peak (×3) 1.9 × 3 ≈ 5.6 Gbps
To origin (5% miss) 5.6 × 0.05 ≈ 0.28 Gbps

Without a CDN you'd need to push almost 6 Gbps from your own servers. With a CDN, one modest S3 bucket is enough.

CDNs and dynamic content

Even uncacheable requests benefit from a CDN:

  • TLS terminates at the edge. The expensive handshake happens with a nearby node, and the CDN already has warm keep-alive connections to the origin over a fast backbone.
  • Microcaching. Responses like "top products" or "feed for logged-out users" can be cached for 1–5 seconds. At 10,000 RPS on such an endpoint, only about one request per second per node reaches the origin.
  • Keyed caching. Vary by Accept-Language or device via Vary or a custom cache key.
  • Edge compute (Cloudflare Workers, Lambda@Edge): A/B redirects, JWT checks, geo-blocking right at the edge.
  • Protection: WAF, rate limiting, and DDoS absorption before the traffic ever reaches you.

Mark personal data (cart, profile) as Cache-Control: private or no-store so it doesn't end up in a shared cache.

Trade-offs worth naming

  • Staleness: until the TTL expires, a user may see an old version. Versioning fixes this.
  • Cost: you pay for egress traffic and requests. At large volumes, multi-CDN or your own nodes pay off, like Netflix Open Connect.
  • Cold cache: rare files (the long tail) often miss. An origin shield helps: a middle cache layer that collapses misses from different nodes into one request to the origin.
  • Harder debugging: "it works for me but not for the user in Tokyo," because you're hitting different nodes.

How it sounds in an interview

"Images and video go into S3 with a CDN in front of it. Static files are versioned with a hash and cached for a year; HTML lives with a one-minute TTL. We expect a 95%+ hit rate, so the origin sees about 5% of the traffic. We use the CDN for the API too: TLS at the edge, microcaching public endpoints for a couple of seconds, and a WAF. Private responses are marked private so they don't leak into the shared cache."

Common mistakes

  • Updating a file under the same name and hoping purge will save you.
  • A long TTL on index.html: after a release, users are stuck on the old version.
  • Caching a response with cookies or personal data as public.
  • Forgetting the origin shield with a large media catalog: thousands of misses hit the storage directly.
  • Saying "a CDN is just for images" and missing the benefits for dynamic content.

If you can draw the diagram above and explain why app.3f9a2c.js can be cached forever, you can handle the CDN topic in an interview with confidence.