Caching & CDNs

Content Delivery Networks (CDNs)

18 min Lesson 7 of 10

Content Delivery Networks (CDNs)

Imagine a user in Singapore loading your website whose origin server sits in Virginia, USA. The raw round-trip time across the Pacific is roughly 180–220 ms — and that is just the network transit, before your server does any work. If the page loads five images, two CSS files, and a JavaScript bundle, the user waits for hundreds of round-trips before the page feels complete. A Content Delivery Network (CDN) eliminates most of that distance by keeping copies of your content on servers scattered around the globe, each one only a few milliseconds away from its nearest users.

CDNs are the planet-scale caching layer that sits between your users and your origin infrastructure. Understanding how they work — and when they fall short — is essential for designing any system that serves users worldwide.

What a CDN Actually Is

A CDN is a geographically distributed network of edge servers (also called Points of Presence, or PoPs). Major providers like Cloudflare, AWS CloudFront, Fastly, and Akamai operate hundreds of PoPs on every continent. When a user requests a resource, their DNS query is routed — via Anycast or DNS-based load balancing — to the nearest PoP. If that PoP has the resource cached, it responds immediately. If not, it fetches the resource from your origin server, caches it locally, and serves it to the user.

Key Concept: A CDN edge server is just a cache that lives close to your users. It speaks HTTP, stores byte-for-byte copies of responses, and uses the same TTL-based expiry and cache-control semantics you already know — just deployed at planet scale.

The Edge / Origin Architecture

The fundamental topology has three tiers: the client, the CDN edge, and the origin. A request always tries the edge first. Only on a cache miss does traffic flow back to the origin. The following diagram shows a single request flowing through this architecture, and how subsequent requests for the same resource never leave the edge.

CDN edge/origin architecture — cache hit vs cache miss flow User — Tokyo ~5 ms to edge User — Paris ~4 ms to edge User — NYC ~3 ms to edge CDN Edge Tokyo PoP cache HIT → serve CDN Edge Paris PoP cache HIT → serve CDN Edge NYC PoP cache MISS → fetch Origin Server Virginia, USA ~180 ms cross-Pacific fetch & cache HIT HIT MISS
CDN edge/origin topology: Tokyo and Paris users get a cache hit at their nearest PoP; the NYC PoP has a cold cache and must fetch from the Virginia origin on first request.

After the NYC PoP fetches the asset from origin and caches it, the next user in New York gets a hit — the origin is no longer involved. This self-warming property means CDN efficiency improves over time as traffic increases, exactly the opposite of what happens to an overwhelmed origin.

Caching Static Content

Static assets — images, fonts, JavaScript bundles, CSS files, videos — are the ideal CDN workload. They change infrequently, are identical for every user, and are often the largest bytes in a page load. A well-configured CDN can serve static assets with:

  • Hit ratio above 99%: A popular image served globally might be fetched from origin only once per PoP per day.
  • Sub-10 ms delivery: Bytes travel less than a few hundred kilometres; physics dominates and the answer is fast.
  • Zero origin load for popular content: If your hero image is viewed 50 million times a day, your origin receives perhaps 300 requests (one per PoP per TTL cycle) — not 50 million.

The standard mechanism is the Cache-Control HTTP header. For static assets versioned by content hash (e.g. main.a8f3bc.js), you can set an extremely long TTL:

Cache-Control: public, max-age=31536000, immutable

The immutable directive tells the CDN (and browsers) that this URL will never change — there is no need to revalidate. When you deploy a new build, you deploy a new URL. Old files stay cached; new files warm up on first access.

Best Practice — Content-Addressed URLs: Name static assets by the hash of their content (a feature of all modern bundlers: Webpack, Vite, esbuild). This gives you infinite cache TTLs with zero stale-content risk. The URL changes only when the content changes.

Caching Dynamic Content

The harder and more interesting problem is serving dynamic content from the edge. Traditional wisdom said CDNs are only for static files. Modern CDNs have broken this rule in several important ways:

1. Vary-by-Cookie / Edge-Side Includes (ESI): The CDN can cache different versions of a page keyed on a cookie or header — for example, a logged-in vs. logged-out variant — and assemble page fragments at the edge. Fastly's ESI and Cloudflare's Vary support enable this.

2. Stale-While-Revalidate: The CDN serves a cached response immediately even if it is slightly stale, then re-fetches from origin in the background. Users never wait for the origin round-trip; the next request after revalidation gets a fresh copy.

Cache-Control: public, max-age=60, stale-while-revalidate=3600

3. Surrogate Keys / Cache Tags: Cloudflare and Fastly let you tag cached objects with arbitrary keys (e.g. product-42). When product 42 changes, you issue a single purge request for that tag and all CDN nodes worldwide invalidate matching entries within seconds. This makes dynamic caching practical even for content that changes frequently.

4. Edge Workers / Compute: Cloudflare Workers, Lambda@Edge (AWS), and Fastly Compute run your code at edge PoPs — enabling custom routing logic, A/B testing, authentication, and personalisation without a round-trip to origin. This is CDN-as-compute, not just CDN-as-cache.

Static vs. Dynamic: Side-by-Side Comparison

CDN static vs dynamic content caching comparison Static Content Examples: images, fonts, JS/CSS bundles video files, PDFs, build artifacts TTL: hours to 1 year (use immutable) Hit ratio: 95–99%+ Same response for ALL users Invalidation: deploy new URL (content-addressed filenames) Dynamic Content Examples: HTML pages, API responses product listings, search results TTL: seconds to minutes (short) Hit ratio: 30–80% (varies by query) May vary by user, locale, A/B group Invalidation: surrogate keys / purge API or stale-while-revalidate
Static vs. dynamic CDN caching: static content is simple with near-perfect hit ratios; dynamic content requires careful TTL and invalidation strategy.

How a CDN Handles Cache-Control Headers

Your origin tells the CDN what to cache and for how long through standard HTTP headers. The CDN acts as a shared proxy cache and respects these directives:

  • Cache-Control: public, max-age=3600 — cache this response at the CDN for 1 hour.
  • Cache-Control: private — do NOT cache at the CDN (only the user's browser can cache it). Use this for personalised responses.
  • Cache-Control: no-store — never cache anywhere. Use for sensitive data (checkout pages, banking).
  • Vary: Accept-Encoding — cache separate copies for gzip vs. brotli responses. The Vary header partitions the cache key.
  • Surrogate-Control (Varnish/Fastly) / CDN-Cache-Control — CDN-only cache TTL that overrides Cache-Control for the edge but not the browser.
Pitfall — Caching Private Data at the Edge: If you forget to set Cache-Control: private on a response containing session-specific data (e.g. a shopping cart, account page), the CDN will cache that user's data and serve it to the next requester for the same URL. This is a data-leakage security incident, not merely a bug. Always audit your cache headers for authenticated endpoints.

CDN Architecture: The Full Request Lifecycle

Full CDN request lifecycle — DNS routing, edge lookup, origin fetch, cache fill Browser User Request Anycast DNS nearest PoP IP CDN Edge Edge Cache Origin Server App + DB 1. DNS 2. TCP/TLS 3. MISS only Cache Lookup key: URL + Vary headers HIT: serve cached response (~5 ms) HIT MISS: fetch origin store + serve (~200 ms) MISS Browser Response Cache HIT path Cache MISS path
Full CDN request lifecycle: DNS routes the user to the nearest PoP; the edge checks its cache and either serves immediately (hit) or fetches from origin and caches the response (miss).

Key Performance Numbers

To make CDN benefits concrete, consider a global e-commerce site before and after CDN adoption:

  • Without CDN (origin in US-East): Singapore users see ~220 ms TTFB; Tokyo users ~180 ms; UK users ~90 ms; US users ~30 ms.
  • With CDN (global PoPs): All users see ~15–30 ms TTFB for cached responses, regardless of origin location.
  • Origin bandwidth savings: Popular static assets may reduce origin egress by 95–99%, directly cutting cloud bandwidth costs.
  • DDoS resilience: CDN PoPs absorb traffic floods close to the source. A 500 Gbps volumetric attack that would flatten a single origin server is spread across hundreds of PoPs, each only seeing a fraction.

When CDNs Do NOT Help (or Make Things Worse)

CDNs are not a universal solution:

  • Highly personalised content: If every user sees unique HTML (e.g. a custom dashboard), the CDN cache key never repeats and the hit ratio is 0%. The CDN adds latency without benefit — consider serving personalised fragments via API and caching the static shell instead.
  • Real-time data that must be fresh: Stock tickers, live sports scores, and financial data cannot tolerate even a few seconds of staleness. Serve these directly from origin or use WebSockets.
  • Writes and mutations: CDNs cache reads. POST, PUT, DELETE requests always pass through to origin.
  • Regions without PoPs: CDN providers vary enormously in their coverage of Africa, South Asia, and Southeast Asia. Always check a provider's PoP map against your user geography.
Design Pattern — Static Shell + Dynamic API: Serve your page skeleton (HTML, CSS, JS) as static assets through the CDN with long TTLs, then fetch user-specific data via authenticated API calls that bypass the CDN. This gives you fast initial paint from the edge plus fresh personalised data — the best of both worlds.

Choosing a CDN Provider

Major providers differ in their strengths:

  • Cloudflare: Best-in-class global coverage (330+ PoPs), free tier, excellent DDoS protection, Workers for edge compute. First choice for most new systems.
  • AWS CloudFront: Deep integration with AWS services (S3, ALB, Lambda@Edge), good choice if your origin is already in AWS.
  • Fastly: Instant purge API (sub-100 ms global invalidation), powerful surrogate key system, VCL programmability. Popular for news and media sites.
  • Akamai: Legacy enterprise CDN; largest PoP network historically but higher cost and complexity.

Summary

A CDN is a geographically distributed cache network that reduces latency by serving content from edge PoPs close to users rather than from a central origin. Static assets — images, fonts, JS/CSS bundles — are the ideal CDN workload, with near-perfect hit ratios and trivial invalidation via content-addressed URLs. Dynamic content can also be cached at the edge using short TTLs, stale-while-revalidate, and surrogate key purging. The most important rules are: set correct Cache-Control headers, never cache private data at the edge, and understand the cases — personalised responses, real-time data, writes — where CDNs provide no benefit or introduce risk.