Content Delivery Network System Design
A Content Delivery Network (CDN) is a globally distributed system of caching proxy servers (and increasingly programmable compute fabric) operated to reduce latency, increase throughput, and improve availability of web and media traffic. The seminal academic reference is Akamai’s 2002 paper “Globally Distributed Content Delivery” by Dilley, Maggs et al., which described the system the company had been operating since 1999 and which essentially defined the field. The mature CDN architecture has since expanded to include edge compute (Cloudflare Workers, Lambda@Edge, Fastly Compute@Edge), DDoS scrubbing, TLS termination and offload, on-the-fly image / video optimization, and edge-side bot management, transforming the CDN from a pure caching layer into a programmable edge platform. The dominant industry players — Akamai (the originator; ~365,000 servers across 4,300+ points of presence in roughly 130–135 countries and 700+ cities per Akamai’s facts page), Cloudflare (the anycast-native upstart; 330+ cities in 125+ countries with a network that crossed 500 Tbps of external capacity, per Cloudflare 2024/25), and Fastly (the developer-focused alternative, fewer but high-density POPs) — implement the same fundamental primitives with different operational characteristics. This note treats them collectively as a single architectural class; all point-in-time figures here are as of early 2026 and drift constantly (see the §9 callout).
1. Functional and Non-Functional Requirements
Functional
- Cache static content — images, scripts, stylesheets, video segments, fonts — at edge POPs (Points of Presence) close to end-users.
- Cache dynamic content with carefully scoped policies (Vary headers, edge-side-include fragments, cache tags).
- Origin fetch — pull content from the customer’s origin server on cache miss, with origin shielding to deduplicate fetches across edges.
- TLS termination — terminate HTTPS at the edge so the customer doesn’t need to manage certificates and TLS performance globally.
- DDoS protection — absorb and filter Layer 3 / 4 floods (SYN floods, UDP amplification, reflection attacks) and Layer 7 attacks (HTTP floods, slowloris, application-layer abuse).
- Routing — direct each user request to the optimal edge POP based on network distance, POP load, and origin proximity.
- Edge compute — run customer code at the edge to do request rewriting, A/B testing, personalization, authentication, image transformation, etc.
- Image / video optimization — resize, recompress, format-convert (WebP, AVIF), and adaptively serve based on client capabilities.
- Purge / invalidation — let customers invalidate cached content immediately by URL, by tag, or globally.
- WAF (Web Application Firewall) — block known attack patterns (SQL injection, XSS, path traversal) before they reach the customer’s origin.
- Bot management — identify and challenge / block automated traffic (scrapers, credential-stuffing tools).
- Geographic policy — geo-blocking, geo-routing, regulatory compliance (GDPR data-residency).
Non-Functional
- Latency reduction — reduce time-to-first-byte by 50–500 ms vs origin-direct fetch, depending on geography and origin location.
- Availability — 99.99%+ for the cached path. Customer origins are an order of magnitude less available; the CDN is what brings the user-perceived number up.
- Capacity — aggregate ingress / egress capacity in the hundreds of Tbps. Cloudflare reported crossing 500 Tbps of external network capacity in 2024/2025 (enough, it claims, to route more than 20% of the web) (Cloudflare); Akamai operates at comparable aggregate scale across its ~365,000-server fleet.
- Cache hit ratio — typical 90%+ for static-heavy customers; 30–60% for dynamic-heavy customers. Hit ratio is the primary lever for both performance and cost.
- DDoS absorption — withstand attacks of multi-Tbps magnitude. Cloudflare and Akamai have publicly mitigated > 5 Tbps attacks (Cloudflare blog disclosures).
- Geographic coverage — sub-50 ms RTT to 95% of human Internet users, requiring 100+ POPs across populated regions.
- Cold-cache origin fill — limit origin egress to manageable rates even on cache-cold launches.
2. Capacity Estimation
Edge POP storage. A typical edge POP has 100s of TB to a few PB of NVMe / SSD across its fleet — enough to hold the working set of the most frequently requested objects for thousands of customers. Cold objects are evicted via LRU Cache-style policies, with admission filters (Bloom Filter or TinyLFU) to avoid one-time fetches polluting the cache.
POP egress. A medium POP serves ~1 Tbps peak egress; a large POP at a major IX serves ~10 Tbps. Aggregating across 100+ POPs gives the global Tbps figures the providers cite.
Origin shield ratio. Without shielding, every cache miss across 100 POPs sends 100 origin fetches for the same object on a cache-cold launch. A shield POP de-duplicates this to 1. The shield-tier traffic is roughly customer_egress / global_hit_ratio — typically 5–20% of total customer traffic.
Anycast announcement. A single anycast IPv4 prefix is announced from every POP via BGP. Internet routers naturally select the topologically-closest POP. No DNS-based routing latency tax.
Cache key cardinality. Per-customer key cardinality is small (millions of distinct objects); aggregate across all customers easily hits hundreds of billions. The key index has to be sparse / sharded to fit in memory.
Edge compute. Cloudflare Workers reports billions of invocations daily across customers. Cold-start for a V8-isolate Worker is about 5 ms (Cloudflare’s own figure), versus 500 ms–10 s for a container-based function like AWS Lambda; once warm, an isolate’s memory overhead drops to roughly 3 MB (Cloudflare).
3. API Sketch
There are three audiences: end users, customers (origin-server operators), and edge compute developers. The “API” looks different to each.
# End user — transparent. The CDN looks like the customer's domain.
GET https://example.com/image.jpg
↳ DNS resolves to anycast IP
↳ TCP / TLS handshake with nearest POP
↳ HTTP request reaches edge cache server
↳ response served (cached or fetched-and-cached)
# Customer — control plane via REST API or dashboard
POST /api/zones → create zone
PUT /api/zones/{id}/cache_settings → configure cache rules
POST /api/zones/{id}/purge → purge by URL or tag
GET /api/zones/{id}/analytics → request stats, hit rate, bandwidth
# Edge compute (e.g., Cloudflare Workers)
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(req) {
if (req.url.endsWith('.webp')) {
return imageOptimizationProxy(req);
}
return fetch(req); // falls through to default cache + origin
}
The most-interfaced API is actually HTTP cache-control headers that the origin server emits and the CDN obeys, normatively defined in RFC 9111 (HTTP Caching, 2022), which obsoletes RFC 7234:
Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=300
ETag: "abc123"
Vary: Accept-Encoding, Accept
max-age is the freshness lifetime for shared and private caches; s-maxage overrides it for shared (CDN) caches; Vary declares which request headers participate in the cache key. One precision worth getting right (an earlier version of this note attributed it to RFC 9111): the stale-while-revalidate and stale-if-error directives are not in RFC 9111 — they are defined in RFC 5861 (“HTTP Cache-Control Extensions for Stale Content”), which RFC 9111 lists only as an informative reference. stale-while-revalidate permits a cache to serve a stale response while asynchronously revalidating in the background; stale-if-error permits serving stale when the origin is unreachable. ETag itself is defined in RFC 9110 (HTTP Semantics), not RFC 9111. The distinction matters because a CDN’s behaviour around stale content is governed by 5861, and a candidate who cites the wrong RFC signals shallow familiarity.
4. Data Model
The CDN’s data layer is unusual because it’s mostly transient — objects come and go; the system is closer to a giant distributed cache than a database.
(A) Per-edge cache store — typically an in-memory key-value index pointing to NVMe / SSD-resident objects. Implementations: Squid (Akamai’s roots), Varnish (Fastly), nginx with custom modules (many providers), pingora (Cloudflare’s Rust-based newer proxy). The cache key is (host, path, query, vary_headers), possibly hashed to 64–128 bits.
(B) Routing / steering data — anycast routes (BGP), GeoDNS records, real-time POP health signals. Updated continuously via control-plane gossip / RAFT-coordinated state.
(C) Zone / customer config — every customer has a config record: origin servers, cache policies, WAF rules, edge compute scripts. Distributed to every POP via a control-plane bus. Cloudflare’s is Quicksilver, a replicated key-value store built on LMDB (it replaced an earlier Kyoto Tycoon setup) that pushes a config change “to 200 cities in 90 countries… within seconds” and, as of its 2020 write-up, served an average of 2.5 trillion reads per day at microsecond read latency. (The 200-cities figure is the 2020 snapshot; the network has since grown past 330 cities — the propagation property, not the count, is the point.)
(D) Analytics / logs — sampled and aggregated request logs, fed back to the customer dashboard. Petabytes per day at scale.
A simplified shape for the cache layer:
cache_index (per edge node, keyed by cache_key):
key: hash of (host, path, query, vary)
storage_uri: pointer to NVMe block where bytes live
size_bytes
status_code
headers: full response header map
expires_at: fresh until
stale_until: serve-stale until (per stale-while-revalidate)
tags: set of customer-supplied tags for tag-based purge
last_used_at: for LRU eviction
customer_config (replicated globally):
zone_id (PK)
origin_uri
cache_rules: pattern → TTL, vary, bypass-on-cookie, etc.
waf_rules: OWASP rule set + customer custom
worker_script: edge-compute code blob
5. High-Level Architecture
flowchart TB subgraph Internet["Public Internet"] Users[End Users<br/>Globally Distributed] end subgraph CDN["CDN Network (300+ cities / POPs)"] Anycast{{Anycast IP<br/>announced via BGP}} subgraph POP_NA["POP — North America"] Edge_NA[Edge Cache Servers] DDoS_NA[DDoS Scrubbing] Compute_NA[Edge Compute<br/>V8 Isolates] end subgraph POP_EU["POP — Europe"] Edge_EU[Edge Cache Servers] DDoS_EU[DDoS Scrubbing] Compute_EU[Edge Compute] end subgraph POP_AS["POP — Asia"] Edge_AS[Edge Cache Servers] DDoS_AS[DDoS Scrubbing] Compute_AS[Edge Compute] end subgraph Shield["Regional Origin Shields"] Shield_NA[Shield NA] Shield_EU[Shield EU] Shield_AS[Shield AS] end end Customer[(Customer<br/>Origin Server)] Users -->|nearest POP via anycast| Anycast Anycast --> Edge_NA & Edge_EU & Edge_AS Edge_NA -.miss.-> Shield_NA Edge_EU -.miss.-> Shield_EU Edge_AS -.miss.-> Shield_AS Shield_NA & Shield_EU & Shield_AS -.miss.-> Customer ConfigCP[Control Plane<br/>Config Distribution] -.config.-> Edge_NA & Edge_EU & Edge_AS Logs[Analytics<br/>Pipeline] <-.logs.- Edge_NA & Edge_EU & Edge_AS
Walk-through. The diagram captures four conceptual layers stacked between users and customer origins. The anycast layer at the top turns one IP into many physical servers — every POP announces the same prefix and BGP picks the nearest. Each POP runs three co-located subsystems: DDoS scrubbing (filters malicious traffic before it reaches caches), edge cache servers (the bulk of the box-count), and edge compute (programmable middleware in V8 isolates). On cache miss, edge servers reach into a regional shield POP that deduplicates origin fetches across dozens of edge POPs. Only on shield miss does traffic reach the customer’s origin. Two cross-cutting flows are not in the user request path: the control plane continuously pushes configuration changes globally (within seconds), and the analytics pipeline continuously pulls logs for billing and customer dashboards. The crucial property: a customer origin that can serve, say, 100 req/sec can serve 100 K req/sec to end users via the CDN, because the CDN absorbs ~99% of the load.
6. Request Flow — A Cache Miss with Origin Shielding
sequenceDiagram participant U as User participant DNS as Recursive DNS participant Edge as Edge POP (nearest) participant Shield as Regional Shield POP participant Origin as Customer Origin U->>DNS: resolve cdn.example.com DNS-->>U: anycast IP (single IP, many POPs) U->>Edge: TCP + TLS handshake (anycast routing picks nearest) U->>Edge: GET /assets/logo.png Edge->>Edge: lookup cache_key → MISS Edge->>Shield: GET /assets/logo.png (with shield-tier headers) Shield->>Shield: lookup cache_key → MISS Shield->>Origin: GET /assets/logo.png Origin-->>Shield: 200 OK + bytes + Cache-Control: max-age=86400 Shield->>Shield: store in shield cache Shield-->>Edge: 200 OK + bytes Edge->>Edge: store in edge cache Edge-->>U: 200 OK + bytes Note over Edge,Shield: Subsequent requests from any edge<br/>in this region hit shield (1 origin fetch total)
The choreography exposes the shielding deduplication: if 50 edge POPs each receive a request for /assets/logo.png simultaneously on a cache-cold launch, the shield receives 50 requests but the customer origin receives just 1. The shield holds the in-flight request and joins concurrent waiters to it (a technique known as “request coalescing” or “single-flight”). Without this, a popular customer’s launch would fan out cache-misses across the entire edge fleet and overwhelm the origin — the so-called cache stampede.
7. Deep Dive — Three Critical Components
7.1 Anycast Routing and POP Selection
The traditional way to direct a user to the nearest POP is DNS-based geo-routing: the authoritative DNS server returns different IPs based on the recursive resolver’s location. Akamai pioneered this approach (the 2002 paper describes it) and continues to use a sophisticated mapping system that updates IP-to-POP assignments based on real-time network measurements.
Cloudflare and Fastly took a different approach: anycast. A single IP prefix (say 1.1.1.1) is announced via BGP from every POP simultaneously. Internet routing protocols (BGP, in particular) naturally route packets to the topologically nearest announcer. The user’s recursive DNS returns the same IP regardless of geography; the routing happens at the IP layer.
Comparing the two:
| Aspect | DNS-Based Routing | Anycast Routing |
|---|---|---|
| Selection mechanism | DNS server picks IP per query | BGP routes packets to nearest announcer |
| Granularity | Per recursive-resolver IP | Per network path |
| Re-routing on POP failure | Requires DNS TTL expiry (minutes) | Automatic via BGP withdrawal (seconds) |
| Granularity of control | Fine — can route per-request | Coarse — at network layer |
| Path stability | Stable until DNS refresh | Can shift mid-connection (rare but possible) |
| Operational complexity | Mapping system is non-trivial | Easier to operate; BGP “just works” |
The path-stability concern with anycast (a TCP connection’s packets routed to different POPs mid-session) is a real edge case but practically rare; once a TCP handshake completes, the route to that source IP tends to be stable because BGP convergence is dominant over per-flow churn. Cloudflare’s explainer on anycast walks through the mechanics.
For L4 load balancing within a POP, both approaches use consistent hashing to keep flow affinity even as backend servers come and go. Google’s Maglev paper (NSDI 2016) describes the production mechanism: a hash table mapping the connection 5-tuple → backend, regenerated periodically with minimal disruption when the backend set changes. See Consistent Hashing and Rendezvous Hashing for the underlying primitives.
It is worth pausing on the lineage here, because it is not a coincidence that CDNs lean on consistent hashing. The technique was invented for exactly this problem: the foundational paper is Karger et al., “Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web” (STOC 1997). Its motivation was web caching — distributing requests for popular content across a changing set of proxy caches so that adding or removing a cache remaps only a K/N fraction of keys instead of nearly all of them. One of the paper’s co-authors, Daniel Lewin, went on to co-found Akamai, turning that theory directly into the first large commercial CDN. So when a CDN hashes a cache key to choose which in-POP cache server owns an object, it is applying the original 1997 use case almost verbatim.
7.2 The Cache Hierarchy and Cache Key Design
A modern CDN runs a 3-tier cache hierarchy within each POP and across POPs:
- In-memory tier — the hottest 1% of objects sit in RAM for sub-microsecond access. Often LRU or W-TinyLFU evicted.
- NVMe / SSD tier — the bulk working set. LRU-evicted; objects live until evicted or expired.
- Cold / regional shield — objects evicted from the edge but still warm at a regional shield POP that aggregates misses across many edges.
- Origin — the absolute fallback.
Cache key design is the most-leveraged optimization. The naive cache key (host, path, query) ignores that the same URL might serve different content depending on Accept-Encoding (gzip vs Brotli vs identity), Accept (WebP vs JPEG), User-Agent (mobile vs desktop), or cookies (logged-in vs anonymous). The HTTP Vary header tells caches which request headers participate in the cache key.
A well-tuned cache key:
- Includes
Varyheaders as part of the key. - Normalizes query parameters (sorts them, strips tracking params).
- Strips cookies that don’t affect content.
- Uses a hash function with low collision (64-bit truncated SHA-256 is overkill; xxHash or wyHash is faster).
Within a POP, requests are distributed across cache servers via Consistent Hashing on the cache key, so the same object lives on the same server regardless of which load-balancer node received the request. This maximizes per-object cache utilization. Adding or removing a cache server moves only ~K/N objects.
Purge mechanisms. Three purge granularities:
- URL purge — invalidate exactly one cache key. Used when a single asset is updated.
- Tag purge — invalidate all keys associated with a customer-supplied tag. The customer emits
Cache-Tag: blog-post-42, all-blog-postsheaders; a single API call to “purge tag all-blog-posts” clears every cached object so tagged. This is what makes purge fast for content-management systems with thousands of pages affected by a single change. - Wildcard / zone purge — invalidate everything for a customer. Drastic; used for emergencies.
On purge speed, get the claim right rather than rounding it into folklore. Cloudflare’s published target is under ~150 ms on average (P50) for its flexible purges — purge by tag, hostname, and URL-prefix — which it reports as a roughly 90% improvement since 2022 (Instant Purge). That number applies specifically to flexible purges; “purge by exact URL” is a simpler operation handled separately. The architectural enabler is what Cloudflare calls “coreless purge”: rather than routing every purge through a few core data centers, it distributes the purge directly to every data center using a store called CacheDB plus Durable Objects, and deletes purged content immediately instead of lazily expiring it (Part 1: Rethinking Cache Purge). Fastly, for its part, has marketed sub-150 ms instant purge for over a decade. The general implementation pattern is a global purge bus that propagates purge events to every edge POP, which then invalidates the affected cache entries; subsequent requests miss and re-fetch.
7.3 Edge Compute — V8 Isolates and the Programmable Edge
The 2018+ wave of CDN evolution is edge compute: customer-supplied code runs at the edge POP, with full access to the request and response, before the response is returned to the user. Cloudflare’s Workers platform is the most-documented example.
The architectural innovation is using V8 isolates (the JavaScript engine’s sandbox primitive) instead of full processes or containers per customer. A single V8 process can host “hundreds or thousands of isolates,” each isolated from the others while sharing the OS process. Cloudflare’s published figures are concrete: an isolate “starts in 5 milliseconds, a duration which is imperceptible,” versus “between 500 milliseconds and 10 seconds” for a Lambda container, and a warm isolate’s memory footprint is around 3 MB versus ~35 MB for a do-nothing Node Lambda (Cloudflare, “Cloud Computing without Containers”). (An earlier version of this note said “microseconds” — the primary source says milliseconds, specifically ~5 ms; the correction matters because the real number, while excellent, is not sub-millisecond.) The security argument is that V8 was designed to be multi-tenant — it already isolates the code of every browser tab within one process — so Cloudflare leans on “perhaps the most well security-tested piece of software on earth” rather than building a new sandbox.
Trade-offs vs container-based edge compute:
- Isolates: faster cold-start, lower memory per tenant, JS / WASM only.
- Containers (Lambda@Edge AWS, Compute@Edge Fastly with WASM-on-VM): slower cold-start, higher per-tenant cost, language-flexible.
Common edge-compute use cases:
- A/B testing and personalization — pick a variant before the cache lookup so the same URL can serve different bytes per cohort.
- Authentication and authorization — verify a JWT before letting the request reach origin or cache.
- Image / video transformation — fetch a single source image, dynamically resize / re-format / re-encode based on
AcceptandViewport-Widthheaders. - Bot detection — challenge suspicious requests with JavaScript proof-of-work or CAPTCHA before allowing access.
- API composition — assemble responses from multiple internal microservices, returning a single payload.
- Static site rendering — server-render React / Vue at the edge against an origin API.
The cache and edge compute interact subtly: a Worker can override the cache key (e.g., key by (URL, country) to serve different content per region) and can decide whether to cache, bypass, or transform the response.
8. Scaling Strategies
Horizontal POP expansion. Add POPs in regions with insufficient coverage. Diminishing returns past ~200 POPs because most users are already within 50 ms of an existing POP.
Cache hit-ratio optimization. Larger working set → better tier-1 hit ratio. Tag-based purges allow finer invalidation (instead of zone-wide nuking on every CMS edit), preserving hit ratio.
Origin shield deployment. Adding shield tiers reduces origin egress, often by 5-20× depending on cache-miss diversity.
TLS session resumption. TLS handshakes are expensive (~1 RTT for TLS 1.3, more for older versions plus crypto cost). Session tickets and PSK (TLS 1.3 0-RTT) lets returning clients skip the handshake. This is a meaningful latency win at edge scale.
Connection multiplexing — HTTP/2 and HTTP/3 (QUIC) let many requests share one connection, reducing per-request connection overhead. CDNs were among the first deployments of QUIC.
Image / video adaptive optimization. Serving WebP instead of JPEG saves 25–35% bytes; AVIF saves more. The CDN auto-converts based on Accept header capabilities.
DDoS scrubbing capacity. Mitigation capacity must exceed the largest plausible attack — providers operate in the multi-Tbps range. Scrubbing happens at the network layer (filtering malformed packets) before traffic reaches application servers, using techniques like SYN cookies, TCP-resetting on suspicious patterns, and rate-limiting via Token Bucket.
Edge compute scaling — V8 isolates per host scale into the thousands; horizontal scaling across edge servers is trivial. Cold starts amortize over the warm pool.
9. Real-World Deployment Notes and Citations
- Akamai: Globally Distributed Content Delivery (Dilley et al., IEEE Internet Computing 2002) and Nygren, Sitaraman & Sun’s “The Akamai network” (ACM 2010) are the canonical references. Akamai operates DNS-based mapping; per its facts page, roughly 365,000 servers across 4,300+ points of presence in ~130–135 countries and 700+ cities — the largest CDN footprint. Co-founder Daniel Lewin co-authored the 1997 consistent-hashing paper (§7.1).
- Cloudflare: extensively blogged at blog.cloudflare.com. Anycast-based routing; 330+ cities in 125+ countries; external capacity past 500 Tbps; control-plane config via Quicksilver; coreless cache purge under ~150 ms; Workers (V8 isolates) is the flagship edge-compute product.
- Fastly: VCL (Varnish Configuration Language)-based cache logic; smaller POP count but high per-POP density; pioneered “instant purge” in the mid-2010s.
- Maglev: Google’s L4 load balancer (Eisenbud et al., NSDI 2016) — the public reference for consistent-hashing-based connection-affinity routing inside a POP.
- HTTP Caching standard: RFC 9111 (2022), the modern successor to RFC 7234, is the normative reference for
Cache-Control,s-maxage,Vary, andAge; the stale-content directivesstale-while-revalidateandstale-if-errorlive in RFC 5861, andETagis defined in RFC 9110 (see §3).
Uncertain
Verify: the specific operational figures (POP/city counts, per-POP capacity, exact server counts, aggregate Tbps). Reason: these are point-in-time marketing/SEC figures that providers update irregularly and inconsistently (Akamai’s “~365,000 servers / 4,300+ PoPs” and Cloudflare’s “330+ cities / 125+ countries / 500 Tbps” are as of late 2024–early 2026). To resolve: re-check each provider’s facts page / latest blog before quoting. Treat all such numbers as approximate and dated. uncertain
10. Tradeoffs
| Dimension | Common CDN Choice | Alternative | Why |
|---|---|---|---|
| Routing | Anycast (Cloudflare, Fastly) or DNS-based (Akamai) | Application-layer routing | Both have strengths; anycast is simpler operationally; DNS is finer-grained |
| Cache backend | NVMe SSD + RAM | All-RAM | Cost — a PB of RAM per POP is infeasible; SSD is 100× cheaper per byte at acceptable latency |
| Eviction | LRU, TinyLFU, W-TinyLFU | LFU | Recency dominates web access patterns; W-TinyLFU adds frequency-aware admission |
| TLS | Terminate at edge | Pass-through | Session resumption and 0-RTT only work if edge terminates; security model is “trust the edge” |
| Origin shield | Regional shield POPs | No shielding | Shield reduces origin egress 5-20×; without it, cache-cold launches melt origins |
| Edge compute runtime | V8 isolates (Cloudflare) or WASM (Fastly) | Containers / functions (Lambda@Edge) | Isolates start in ~5 ms; containers start in 500 ms–10 s — a multi-order-of-magnitude latency difference |
| Purge | Tag-based + URL + zone | URL-only | CMS workloads have many URLs affected by one logical change; tag purge is essential |
| DDoS mitigation | At-edge filtering | Customer-side | Edge has the capacity; customer doesn’t |
| Cache key | Customer-controlled via Vary + edge code | Fixed (host, path, query) | Real workloads need locale, viewport, encoding, A/B variant in the key |
11. Pitfalls and Gotchas
- Cache stampede / thundering herd. When a popular object expires, every concurrent request from every edge fetches origin simultaneously. Mitigation: request coalescing at edge and shield (single-flight);
stale-while-revalidateto serve stale while async-refreshing;stale-if-errorto keep serving on origin failure. - Vary explosion. Including too many request headers in the cache key shatters the working set into singletons — every user has a unique cache entry. The classic offender is
Vary: User-Agentwith no normalization (each browser version is a different cache entry). Always normalize Vary headers aggressively. - Cookies in cache key. A naive
Vary: Cookiemakes every logged-in user’s cache entry distinct; effective cache hit rate plummets. Better: bypass cache for authenticated requests, or strip non-functional cookies before keying. - Stale content after origin update. TTL-based caching means stale content lingers until expiry. Tag-based purge solves this if origin emits the right tags; many origins don’t, so customers learn this only when a typo persists for 24 hours.
- TLS certificate management at scale. Serving HTTPS for millions of customer hostnames requires millions of certificates. Cloudflare and others use SAN (Subject Alternative Name) certificates and ACME / Let’s Encrypt automation; private keys are distributed to every POP, raising compromise concerns; some providers offer “Keyless SSL” where signing happens at customer-controlled servers.
- Origin overload after large purge. A zone-wide purge invalidates everything; the next user request starts re-filling the cache from origin. Without rate-limiting, the origin can be overwhelmed faster than during normal cache-warm operation. Some CDNs throttle post-purge origin traffic.
- DNSSEC and anycast incompatibility. DNSSEC validation can be tricky over anycast because validators expect consistent responses and anycast resolvers can shift mid-resolution. Generally well-handled today but historically a debugging headache.
- Edge compute cold start cost. Workers / Functions warm-pool size determines cold-start frequency. A rare-but-popular customer (e.g., a newspaper paywall script invoked on most pageviews) keeps its isolate warm; an obscure script suffers cold-start on every invocation.
- Geo-IP misclassification. A user behind a VPN or non-default routing can appear to be in a wrong country. Geo-blocking and content licensing decisions made on this basis create real customer-experience failures.
- Path-MTU issues with QUIC over anycast. QUIC requires the network path to support a particular MTU; misconfigured intermediate routers cause silent failures. Providers monitor this carefully but it has surfaced in practice.
12. Common Interview Variants
- Design a CDN — the canonical prompt; sometimes specialized to “design Cloudflare” or “design a CDN for video”.
- Design a video CDN — see YouTube Video Streaming System Design and Netflix Streaming System Design for video-specialized variants.
- Design DNS — see Domain Name System Design; CDNs depend on it for DNS-based routing.
- Design DDoS protection — extracted scrubbing-layer problem.
- Design an edge compute platform — focus on V8 isolates, sandbox security, customer-code-on-shared-infrastructure.
- Design an L4 load balancer — see Load Balancer System Design; Maglev-class system with Consistent Hashing.
- Design image optimization service — extracted variant; on-the-fly resize / re-encode based on client capabilities.
13. Open Questions and Areas of Uncertainty
- How does CDN economics shift as connectivity reaches saturation in the developed world? Is the next decade about deepening (adding density in underserved regions) or specializing (per-vertical optimization)?
- Will the V8-isolates vs WASM-on-VM split converge, or do they remain ecologically distinct (Cloudflare camp vs Fastly camp)?
- How does the TLS / certificate-management complexity scale with the proliferation of post-quantum cryptography requirements?
- Is the “origin shield” tier on a path to obsolescence as CDNs grow large enough that intra-CDN deduplication happens automatically through other mechanisms?
- What is the performance / cost crossover where a customer should use multiple CDNs concurrently (multi-CDN steering) vs accepting single-CDN dependence?
Uncertain
Multi-CDN steering, post-quantum TLS, and edge-compute runtime convergence are live industry questions as of 2024–2026. Cite contemporary sources before quoting answers.
14. See Also
- Major System Designs MOC
- SWE Interview Preparation MOC
- YouTube Video Streaming System Design — first-party CDN for UGC video
- Netflix Streaming System Design — Open Connect first-party CDN for licensed video
- Spotify Audio Streaming System Design — audio CDN
- Twitch Live Streaming System Design — live-streaming CDN with low-latency requirements
- Consistent Hashing — cache-server selection within a POP; Maglev variant
- Rendezvous Hashing — alternative to consistent hashing for affinity
- Bloom Filter — admission filters to avoid one-time-fetch cache pollution
- LRU Cache — per-cache-server eviction
- Token Bucket — DDoS rate limiting and customer rate-limit primitives
- Domain Name System Design — DNS-based routing alternative to anycast
- Load Balancer System Design — Maglev-class L4 load balancing
- API Gateway System Design — adjacent edge-of-network primitive
- Dropbox File Sync System Design — the storage-side cousin: Dropbox’s Magic Pocket optimizes durable origin storage of immutable blocks, whereas a CDN optimizes edge delivery of cacheable bytes; both lean on content-addressing and consistent hashing