Design a Content Delivery Network (CDN)

PoP Architecture, Cache Strategies, Invalidation, SSL Termination, and Real-World CDN Configurations

A Content Delivery Network is a geographically distributed system of proxy servers that caches and delivers content from locations closest to end users. CDNs reduce latency by minimizing the physical distance data travels, offload traffic from origin servers, and improve availability through redundancy. Modern CDNs serve over 50% of all internet traffic β€” powering everything from static assets and video streaming to API responses and dynamic page rendering. The core design decisions revolve around where to place Points of Presence (PoPs), how to route requests to the nearest edge, which caching strategy to use (push vs. pull), and how to handle cache invalidation without sacrificing consistency. A well-designed CDN can reduce origin load by 90%+ and cut page load times from seconds to milliseconds.

Why CDNs Matter

The speed of light imposes a hard floor on latency. A CDN brings content closer to users, dramatically cutting round-trip times.

~200ms
Cross-continent RTT

New York to Sydney round-trip through fiber optic cables β€” physics can't be cheated.

~5ms
Edge PoP RTT

Same content served from a local PoP β€” 40x faster than crossing oceans.

90%+
Origin offload

Typical cache hit ratio for static content. Origin only handles cache misses.

53%
Users leave at 3s

Google research: 53% of mobile users abandon sites that take >3 seconds to load.

Latency Calculator

Compare response times with and without a CDN. Adjust the origin distance and see how cache hits vs. misses affect the user experience.

Without CDN

DNS Lookup 50ms
TCP Handshake 160ms
TLS Negotiation 160ms
Request β†’ Origin 80ms
Origin Processing 50ms
Response Transfer 80ms
Total 580ms

With CDN

DNS Lookup 20ms
TCP Handshake (edge) 10ms
TLS (edge) 15ms
Request β†’ PoP 5ms
Cache / Origin β€”
Effective (blended) β€”
No CDN: 580ms
With CDN: β€”

PoP Architecture & Anycast Routing

CDNs use a globally distributed network of Points of Presence (PoPs) to serve content as close to users as possible. Each PoP is a cluster of proxy servers in a single datacenter location, typically housing 50–500 servers.

User (NYC)
β†’
GeoDNS
β†’
NYC PoP
β†’
Origin (SF)
↓ Cache Hit
Cached Response
↓ Cache Miss
Origin Fetch

Anycast Routing

CDNs announce the same IP address from hundreds of PoPs worldwide. DNS returns the nearest PoP based on BGP routing. When a PoP receives too much traffic, BGP naturally reroutes to the second-closest PoP β€” automatic load balancing at the network layer.

// Cloudflare Anycast example
// Their edge nodes announce 104.16.0.0/12 from 300+ PoPs
// BGP routes user to nearest PoP automatically
route 104.16.0.0/12 via 198.51.100.1
// User in London β†’ London PoP (5ms)
// User in Tokyo β†’ Tokyo PoP (8ms)
// No single origin IP needed at application layer
          

PoP Hierarchy

Most CDNs use a tiered cache hierarchy β€” regional "mid-tier" caches that serve multiple city-level PoPs. This reduces origin fetch traffic significantly.

  • Edge PoP (Tier 3) β€” City-level, serves 1–5ms latency to end users
  • Regional PoP (Tier 2) β€” Country-level, aggregates 5–20 edge PoPs, larger cache
  • Origin Shield (Tier 1) β€” Continent-level, minimizes origin fetches, full cache

CDN Architecture Simulator

Nearest PoPβ€”
Edge latencyβ€”
Cacheableβ€”
Shield PoPβ€”

Cache Strategies: Push vs. Pull

The two fundamental CDN cache models differ in who initiates content placement and when. The right choice depends on your update frequency and control requirements.

Push CDN

Origin β†’ CDN

You upload content directly to CDN when it changes. The origin controls exactly what lives on the edge and when it updates.

1. Content uploaded to origin
β†’
2. Origin pushes to CDN
β†’
3. CDN propagates to all PoPs
Pros
  • Precise control β€” content appears exactly when you want
  • No stale content β€” no "cache miss" latency on first request
  • Efficient for infrequently-updated content
  • No extra origin requests ever needed
Cons
  • You must explicitly push every update
  • Easy to forget to push after content changes
  • Higher storage cost β€” content lives everywhere even if unvisited
# Nginx + Push CDN example (Fastly)
// On content publish, PUT to Fastly
curl -X POST "https://api.fastly.com/purge/example.com/css/style.css"
{
  "status": "ok",
  "id": "7-1234567890abcdef"
}
# Or configure auto-purge on origin backend
backend = "https://your-origin.com"
surrogate_key = "static-asset"
cache_control = "max-age=31536000, public"
          

Pull CDN

CDN β†’ Origin

CDN fetches content from origin on first request (cache miss) and caches it. Most common model for web content.

1. First request hits CDN
β†’
2. CDN fetches from origin
β†’
3. CDN caches and serves
Pros
  • Zero effort on content publish β€” just update origin
  • Only popular content consumes CDN storage
  • Simpler origin integration (no push API needed)
Cons
  • First request always slow (origin latency)
  • Thunderin herd on cache miss β€” popular content can stampede origin
  • Harder to guarantee freshness
# Cloudflare Page Rules β€” Pull-based caching
# Rule: *.example.com/images/*
#   Cache Level: Cache Everything
#   Edge Cache TTL: 1d
#   Browser Cache TTL: 1h
#   Origin: https://origin.example.com

# The CDN pulls from origin on first cache miss
# Subsequent requests served from edge cache
          

Strategy Comparison Calculator

Push CDN storage β€”
Pull CDN storage (estimated) β€”
Push CDN bandwidth β€”
Pull CDN origin fetches/day β€”
Recommended strategy β€”

Cache Invalidation & Freshness

Once content is cached at the edge, how do you get rid of it? Cache invalidation is one of the hardest problems in CDN design β€” you need to balance between keeping content fresh and maintaining high cache hit ratios.

Invalidation Methods

Purge by URL

Sends a deletion request for a specific URL. Fastest for single-asset updates. Cloudflare, Fastly, and Akamai all support this via API.

// Cloudflare API purge
curl -X POST "https://api.cloudflare.com/client/v4/zones/abc123/purge" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"files":["https://example.com/css/style.css"]}'

// Response
{"result":{"id":"2hy3x1h3j2x4z"},"success":true}
Purge by Cache-Tag / Surrogate Key

Tag groups of related content (e.g., all assets from a specific page). Invalidate entire tag in one call. Great for product catalog updates.

// Fastly surrogate key purge
// Set headers on origin response:
// Surrogate-Key: product-12345 category-shoes

// Purge all assets with that key
curl -X POST "https://api.fastly.com/purge/$SERVICE_ID/product-12345"
{"status":"ok","purged":14}
              
Purge All (Emergency)

Invalidates entire cache. Use sparingly β€” causes massive origin load spike. Essential for security incidents.

// Akamai cache purge
POST /ccu/v3/invalidate/content
{
  "type": "cpcode",
  "objects": ["123456"]
}
# Purges everything under CP code 123456
              
TTL-based Expiry

Set Cache-Control: max-age=N or Expires: headers. Content automatically expires after N seconds. Simplest but cannot fix errors quickly.

# Strong caching β€” long TTL, explicit invalidation
Cache-Control: public, max-age=31536000, immutable
# "immutable" tells browser/CDN: this URL NEVER changes
# Only purge when you have a real emergency

# Soft caching β€” shorter TTL for fresher content
Cache-Control: public, max-age=3600, stale-while-revalidate=60
# Serve stale for up to 60s while fetching fresh
              

Stale-While-Revalidate Pattern

The stale-while-revalidate directive is the CDN operator's best friend. It serves stale content immediately while fetching a fresh copy in the background β€” eliminating the "first request is slow" problem for Pull CDNs.

# Response from origin:
Cache-Control: public, max-age=3600, stale-while-revalidate=86400

# Meaning:
# - Cache for 1 hour
# - If stale (up to 24h after expiry), serve stale immediately
#   while asynchronously revalidating from origin
# - After 24h of staleness, block and wait for origin

# This gives you: fast responses + eventual consistency
# P99 latency drops from ~500ms (origin fetch) to ~5ms (stale served)
          

Note: stale-while-revalidate is now supported by Cloudflare, Fastly, and Akamai. It's part of the official HTTP RFC 5861 spec.

Cache Hit Ratio Optimizer

Expected cache hit ratio β€”
Avg staleness (how old cached content is) β€”
Origin load reduction β€”
Invalidation recommended β€”

SSL/TLS Termination at the Edge

CDNs terminate TLS at the edge, meaning the CDN handles encryption with end users while communicating with your origin over a private link (often with its own certificate or none at all). This is called "SSL offload" and it's a primary reason companies use CDNs.

How Edge TLS Works

User β†’ Edge PoP
HTTPS request with TLS 1.3. ECDHE for perfect forward secrecy. Edge has the public certificate (e.g., *.example.com).
β†’ (encrypted)
Edge PoP β†’ Origin
CDN connects to origin over private backbone, often unencrypted or with origin-specific certificate. No public internet exposure.

Origin Connection Options: CNAME to CDN origin, direct IP, or private peering. Modern CDNs use Anycast-origin architecture β€” traffic between PoPs and origin never leaves the CDN's network.

Certificate Management

# Cloudflare Automatic HTTPS Rewrites
# CDN auto-detects resources loaded over HTTP and rewrites to HTTPS
# Solves mixed content issues without origin changes

# Option 1: Cloudflare Origin Certificate (free, internal only)
# Issued by Cloudflare, only valid when accessed via Cloudflare
# Perfect for internal origin servers
openssl req -new -newkey rsa:2048 -nodes -keyout origin.key \
  -out origin.csr  # Sign with Cloudflare Origin CA

# Option 2: Bring Your Own Certificate (BYOC)
# Upload your existing cert to the CDN
# Works if you need to access origin directly too

# Option 3: Let's Encrypt on origin
# Origin runs its own cert issuer
# CDN validates cert via ACME protocol
          

TLS 1.3 Performance Gains

TLS 1.3 reduces handshake from 2 RTTs to 1 RTT (0-RTT for resumption). For a user connecting to a distant PoP, this saves ~50–100ms on every new connection.

FeatureTLS 1.2TLS 1.3
Full handshake2 RTTs1 RTT
Resumption1 RTT0 RTT
PFS (forward secrecy)OptionalMandatory
Supported by CDNsAllAll major

HTTP/2 & HTTP/3 (QUIC)

Modern CDNs support HTTP/2 multiplexing and HTTP/3 over QUIC. HTTP/3 eliminates head-of-line blocking by using UDP β€” a major win for mobile users on unreliable connections.

# Cloudflare HTTP/3 (QUIC) enablement
# It's on by default for all plans
# Edge announces via Alt-Svc header:
Alt-Svc: h3=":443"; ma=86400

# What this means for performance:
# - 0-RTT connection resumption (TLS 1.3)
# - Multiplexing without head-of-line blocking
# - Connection migration (WiFi β†’ Cell without reconnect)
# - 20-40% latency improvement on mobile
          

Real CDN Configurations

Each major CDN has its own architecture, API style, and configuration model. Here's how to configure the three industry leaders for common scenarios.

# Cloudflare Page Rules β€” Cache static assets aggressively
# Rule priority order matters (first match wins)
URL pattern: static.example.com/images/*
  Cache Level: Cache Everything
  Edge Cache TTL: 1w
  Browser Cache TTL: 1d
  Origin Cache Control: On
  WebP: On (auto-convert images)
  Mirage: On (lazy-load images)
  Polish: lossy (compress images at edge)

URL pattern: api.example.com/*
  Cache Level: Bypass
  // API responses should never be cached by default

URL pattern: *.example.com/product/*
  Cache Level: Standard
  Cache TTL: 1h
  Purge Tag: product-[ID] on update

# Cloudflare Workers β€” Custom cache logic
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const cache = caches.default;
  const url = new URL(request.url);

  // Check cache first
  let response = await cache.match(request);

  if (!response) {
    // Fetch from origin
    response = await fetch(request);

    // Add custom cache headers
    response = new Response(response.body, response);
    response.headers.set(
      'Cache-Tag',
      `product-${url.searchParams.get('id')}`
    );
    response.headers.set(
      'Cache-Control',
      'max-age=3600, stale-while-revalidate=86400'
    );
  }

  return response;
}
        
Cloudflare special features: Workers (edge computing), Images (optimized image delivery), R2 (object storage without egress fees), D1 (edge SQLite), KV (edge key-value store), Stream (video platform).

Multi-CDN Strategy

Large-scale services rarely use a single CDN. Multi-CDN architectures provide resilience, leverage strengths of different providers, and allow traffic optimization based on geography and performance.

Why Multi-CDN?

  • Resilience β€” If one CDN has an outage (it happens), traffic fails over to another. Netflix, Google, and Cloudflare have all had major outages.
  • Best-of-breed β€” Cloudflare excels at DDoS protection, Fastly at caching logic, Akamai on video/large file delivery. Use each where it shines.
  • Cost optimization β€” Egress pricing varies significantly. Multi-CDN allows arbitraging between providers.
  • Geographic coverage β€” No single CDN has optimal PoPs everywhere. Multi-CDN fills gaps in emerging markets.

Architecture Patterns

1. DNS-based failover

Primary CDN at normal priority, secondary at fallback. Use different CNAMEs. Simplest to implement but slowest to fail over.

# DNS configuration
cdn-primary.example.com  CNAME primary.cdn.com.
cdn-secondary.example.com CNAME secondary.cdn.com.

# On primary failure, CNAME to secondary
# Health check every 30s via your load balancer
            
2. BGP Anycast spread

Announce overlapping IP prefixes to multiple CDNs. Traffic splits based on BGP path length. Natural load balancing but requires CDN coordination.

3. Application-layer traffic steering

At the origin, inspect request headers to determine which CDN made the request. Route accordingly. Most flexible but most complex.

Multi-CDN Traffic Controller Simulator

Single CDN downtime/monthβ€”
Multi-CDN downtime/monthβ€”
Failed requests avoided/monthβ€”
Max consecutive downtimeβ€”

CDN Capacity Estimation

Sizing your CDN requirements involves understanding bandwidth, storage, request rates, and PoP distribution.

Peak bandwidthβ€”
Monthly egress (GB)β€”
Edge storage neededβ€”
Origin bandwidth savedβ€”

Key Design Decisions

Cache Strategy Decision Tree

Content changes frequently?
β†’ Pull CDN + short TTL + stale-while-revalidate
Content is versioned (hashed URLs)?
β†’ Push CDN + immutable + very long TTL
Need instant updates on change?
β†’ Pull CDN + surrogate key purging
Has a known set of popular content?
β†’ Push CDN + prefetch on publish

CDN Selection Criteria

NeedBest CDN
DDoS protection + securityCloudflare
Performance + instant purgeFastly
Video streaming + large filesAkamai
Cost optimization + simplicityCloudFront / Cloudflare
Enterprise + global satelliteAkamai
Developer-friendly edge computeFastly (Compute) / Cloudflare (Workers)

CDN Health Checklist

βœ“ Enable HTTP/2 or HTTP/3
βœ“ Enable TLS 1.3 where supported
βœ“ Set stale-while-revalidate for soft TTLs
βœ“ Configure surrogate key tagging for bulk invalidation
βœ“ Set origin shield / mid-tier for origin protection
βœ“ Enable brotli or zstd compression at edge
βœ“ Configure image optimization (WebP, AVIF, lazy-load)
βœ“ Set up real-time cache hit/miss monitoring alerts
βœ“ Plan for CDN failure (multi-CDN or fallback origin)
βœ“ Version static assets via content hashing