Home/Learn/Computer Networks/CDN (Content Delivery Network)

CDN (Content Delivery Network)

Intermediate
Infrastructure

A CDN is a globally distributed network of edge servers that cache and serve content from locations close to users — reducing latency, decreasing origin load, and improving availability.

Overview

A CDN places copies of your content (static assets, API responses, video) at hundreds of Points of Presence (PoPs) worldwide. When a user requests a resource, DNS resolves to the nearest PoP. If the PoP has a cached copy (cache hit), it serves directly — often within 5–10ms. On a cache miss, the PoP fetches from the origin and caches the response. CDNs also provide DDoS protection, SSL termination, WAF, and image optimization. Cloudflare, AWS CloudFront, and Fastly are the dominant providers. Understanding CDN cache headers, invalidation, and edge compute is critical for frontend-heavy and high-traffic applications.

How CDN Routing Works

CDNs use Anycast DNS or GeoDNS to route users to the nearest PoP. Anycast advertises the same IP from multiple locations — BGP routing naturally sends traffic to the closest PoP. GeoDNS resolves the same hostname to different IPs based on the user's geography.

CDN routing and CloudFront configuration
// CDN request flow:
// 1. User in Mumbai requests: https://aicancode.org/logo.png
// 2. DNS query for aicancode.org → CDN GeoDNS returns Mumbai PoP IP (e.g. 104.18.x.x)
// 3. Browser connects to Mumbai PoP
// 4. PoP checks cache: HIT → serve immediately (~5ms)
//                      MISS → fetch from origin (e.g. Vercel/AWS), cache, serve
//
// Cache key: typically scheme + host + path + (optionally) query string
// X-Cache: HIT / MISS / REFRESH_HIT in response headers

// CloudFront distribution (Terraform):
resource "aws_cloudfront_distribution" "cdn" {
  origin {
    domain_name = "api.aicancode.org"
    origin_id   = "api-origin"
  }
  default_cache_behavior {
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    viewer_protocol_policy = "redirect-to-https"
    cache_policy_id        = aws_cloudfront_cache_policy.default.id
  }
  price_class = "PriceClass_200"  // all PoPs except South America
  enabled     = true
}

Cache-Control Headers for CDN

The CDN respects HTTP Cache-Control headers set by the origin. Getting these right is essential: over-caching stale content; under-caching kills CDN effectiveness and hammers the origin.

Cache-Control headers for CDN optimization
// Cache-Control directives for CDN:

// Immutable static assets (hashed filenames: app.a1b2c3.js)
// Browser AND CDN cache forever — never revalidate
Cache-Control: public, max-age=31536000, immutable

// Dynamic HTML pages — CDN caches for 60s, browser no-cache
Cache-Control: public, s-maxage=60, max-age=0, must-revalidate
// s-maxage applies to CDN (shared cache); max-age to browser

// API responses — no CDN caching, browser can cache briefly
Cache-Control: private, max-age=30

// Never cache (user-specific, sensitive)
Cache-Control: no-store

// Next.js sets these automatically:
// /_next/static/*   → immutable, 1-year
// /api/*            → no-store (by default)
// pages             → s-maxage=1, stale-while-revalidate (ISR)

// Vary header — cache separate versions per header value:
Vary: Accept-Encoding            // separate cache for gzip vs identity
Vary: Accept-Language            // separate cache per language

Cache Invalidation

When content changes, cached versions at PoPs must be invalidated. The two primary strategies are: versioned URLs (rename files with a content hash — old URL is simply never requested again) and explicit purge (API call to CDN to evict a URL or prefix). Versioned URLs are preferred for static assets; purge is used for HTML pages or API responses.

CDN cache invalidation strategies
// Strategy 1: Versioned URLs (preferred for static assets)
// Build tool (webpack/Next.js) generates content-hash filenames:
// app.js → app.a1b2c3d4.js
// When content changes → new hash → new URL → CDN auto-fetches fresh copy
// Old URL simply stops being referenced → naturally expires after max-age

// Strategy 2: Explicit purge (CloudFront invalidation)
aws cloudfront create-invalidation \
  --distribution-id E1ABC123DEF456 \
  --paths "/index.html" "/api/courses*"

// Cloudflare purge by URL:
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  --data '{"files":["https://aicancode.org/courses","https://aicancode.org/"]}'

// Surrogate Keys / Cache Tags (Fastly, Cloudflare):
// Origin sets: Surrogate-Key: course-123 user-456
// On update: purge by tag "course-123" → all pages tagged with it are evicted
// Much more granular than path-based purge

Edge Computing

Modern CDNs (Cloudflare Workers, AWS Lambda@Edge) allow running JavaScript at the edge, before the request reaches the origin. Use cases: A/B testing without origin round-trip, auth token validation, geo-based redirects, request/response transformation.

Edge compute: Cloudflare Workers and Lambda@Edge
// Cloudflare Worker — A/B test at the edge
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const url = new URL(request.url)

  // Route 10% of traffic to /beta endpoint
  const variant = Math.random() < 0.1 ? 'beta' : 'stable'
  url.pathname = variant === 'beta' ? '/beta' + url.pathname : url.pathname

  const response = await fetch(url.toString(), request)
  return new Response(response.body, {
    ...response,
    headers: { ...response.headers, 'X-AB-Variant': variant }
  })
}

// Lambda@Edge — add security headers to every CloudFront response:
exports.handler = async (event) => {
  const response = event.Records[0].cf.response
  response.headers['strict-transport-security'] = [{
    key: 'Strict-Transport-Security',
    value: 'max-age=31536000; includeSubDomains'
  }]
  return response
}

Key Points to Remember

  • 1A CDN cache hit serves from a PoP milliseconds away; a miss fetches from origin and populates the edge cache for subsequent requests.
  • 2Use content-hash filenames for static assets with max-age=31536000 immutable — no invalidation ever needed.
  • 3Use s-maxage (CDN TTL) separate from max-age (browser TTL) for HTML pages served via CDN.
  • 4Explicit purge is needed for HTML pages and API responses; versioned URLs are self-invalidating for static assets.
  • 5Edge compute (Cloudflare Workers, Lambda@Edge) enables A/B testing, auth, and geo-redirects without origin round-trips.

Interview Questions

Sign in to ask Aria
1

How does a CDN decide which PoP serves a user's request?

MediumThoughtWorks
2

What is the difference between max-age and s-maxage in Cache-Control?

MediumFlipkart
3

How would you handle CDN cache invalidation after a deployment?

MediumRazorpay
4

What are Surrogate Keys and why are they useful for cache invalidation?

HardAmazon
5

What can you do with edge computing (Cloudflare Workers) that you cannot do at the origin?

HardEqual Experts

Ask Aria about CDN (Content Delivery Network)

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…