Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

CDN & Edge Caching

Bringing content closer to users worldwide

Imagine a user in Tokyo trying to load a website hosted in New York. Every request travels 10,000+ kilometers, adding 200-300ms of latency just from distance.

Diagram

The problem: Geographic distance creates unavoidable latency. Even with fast networks, physics limits speed of light.

The solution: CDN (Content Delivery Network) - cache content at edge locations worldwide, closer to users.


CDN = Network of distributed servers that cache content at edge locations close to users.

Diagram
  1. User requests content (e.g., example.com/image.jpg)
  2. DNS routes to nearest edge server
  3. Edge server checks cache
    • Hit: Return cached content (fast!)
    • Miss: Fetch from origin, cache it, return to user
  4. Subsequent requests served from edge (fast!)

Content that doesn’t change:

  • Images (JPG, PNG, SVG)
  • CSS files
  • JavaScript files
  • Fonts
  • Videos
  • HTML (if static)
Diagram

Why static content is perfect:

  • Same for all users
  • Rarely changes
  • Can cache for long time (days/weeks)
  • Large files (benefit from edge caching)

Content that changes, but can still be cached:

  • API responses (with appropriate TTL)
  • User profiles (public parts)
  • Product catalogs
  • News articles
  • Search results (with short TTL)
Diagram

Considerations:

  • ⚠️ Use appropriate TTL (shorter than static)
  • ⚠️ May need cache invalidation
  • ⚠️ Consider user-specific data carefully

Content that shouldn’t be cached:

  • Real-time data (stock prices, chat)
  • User-specific sensitive data (account balance)
  • Personalized content (shopping cart)
  • Authentication tokens
  • One-time use data (OTP codes)

Design your APIs to work well with CDN caching:

Cache-Control header controls caching behavior:

cache_headers.py
from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.route('/products')
def get_products():
products = fetch_products()
response = make_response(jsonify(products))
# Cache for 5 minutes (public = CDN can cache)
response.headers['Cache-Control'] = 'public, max-age=300'
# ETag for validation
response.headers['ETag'] = generate_etag(products)
return response
@app.route('/user/profile')
def get_user_profile():
profile = fetch_user_profile()
response = make_response(jsonify(profile))
# Don't cache (private, user-specific)
response.headers['Cache-Control'] = 'private, no-cache'
return response
@app.route('/static/image.jpg')
def get_image():
# Static content - cache for 1 year
response = make_response(send_file('image.jpg'))
response.headers['Cache-Control'] = 'public, max-age=31536000'
return response
DirectiveMeaningExample
publicCDN can cachepublic, max-age=3600
privateOnly browser can cacheprivate, max-age=3600
no-cacheRevalidate before useno-cache
no-storeDon’t cache at allno-store
max-age=NCache for N secondsmax-age=300 (5 min)
must-revalidateMust revalidate when expiredmust-revalidate

Add version to static assets to enable long caching:

Bad: /static/app.js (can't cache long - might change)
Good: /static/app.v1.2.3.js (can cache forever - new version = new URL)

How it works:

  1. Deploy new version → new URL (app.v1.2.4.js)
  2. Old URLs still cached (forever)
  3. New requests get new version
  4. No cache invalidation needed!
"versioned_assets.py
from flask import Flask, url_for
app = Flask(__name__)
# In your template
@app.route('/')
def index():
version = "1.2.3"
return f"""
<html>
<link rel="stylesheet" href="/static/styles.v{version}.css">
<script src="/static/app.v{version}.js"></script>
</html>
"""

Split your API into cacheable and non-cacheable endpoints:

Diagram

Example:

  • /products → Cacheable (same for all users)
  • /user/cart → Not cacheable (user-specific)
  • /public/profile/:id → Cacheable (public profile)
  • /user/profile → Not cacheable (private, authenticated)

ETag = hash of content. Allows “conditional requests”:

Request: GET /products
If-None-Match: "abc123"
Response: 304 Not Modified (if ETag matches)
or 200 OK with new ETag

Benefits:

  • Saves bandwidth (304 = no body)
  • Validates freshness
  • Works with CDN

Simplest pattern - CDN only for static files:

Diagram

When to use:

  • Simple setup
  • Static website
  • API doesn’t need caching

CDN caches API responses too:

Diagram

When to use:

  • Global user base
  • API responses cacheable
  • Need low latency worldwide

LLD Connection: Designing Cache-Friendly Services

Section titled “LLD Connection: Designing Cache-Friendly Services”

At the code level, design your services to be cache-friendly:

"cache_friendly_service.py
from abc import ABC, abstractmethod
from typing import Optional
from datetime import datetime, timedelta
class ProductService(ABC):
@abstractmethod
def get_products(self) -> list:
pass
class DatabaseProductService(ProductService):
def get_products(self) -> list:
# Fetch from database
return db.query("SELECT * FROM products")
class CacheableProductService(ProductService):
def __init__(self, db_service: ProductService, cache: CacheClient):
self.db_service = db_service
self.cache = cache
self.cache_key = "products:all"
self.ttl = 300 # 5 minutes
def get_products(self) -> list:
# Try cache first
cached = self.cache.get(self.cache_key)
if cached:
return cached
# Cache miss - fetch from DB
products = self.db_service.get_products()
# Cache it
self.cache.set(self.cache_key, products, ttl=self.ttl)
return products
def invalidate_cache(self):
"""Call this when products are updated"""
self.cache.delete(self.cache_key)
class HTTPResponseBuilder:
@staticmethod
def build_cacheable_response(data, ttl: int = 300):
"""Build HTTP response with proper cache headers"""
return {
'data': data,
'headers': {
'Cache-Control': f'public, max-age={ttl}',
'ETag': generate_etag(data)
}
}
@staticmethod
def build_private_response(data):
"""Build HTTP response that shouldn't be cached"""
return {
'data': data,
'headers': {
'Cache-Control': 'private, no-cache'
}
}

Major companies use CDNs to deliver content globally with low latency:

The Challenge: Websites need to serve content to users worldwide. Serving from a single origin server causes high latency for distant users.

The Solution: Cloudflare CDN with 300+ edge locations:

  • Static assets: Images, CSS, JS cached at edge for days/weeks
  • Dynamic content: API responses cached at edge for minutes
  • Geographic distribution: Content served from nearest edge location

Example: User in Tokyo requests website:

  • Without CDN: Request → US origin server (200ms latency)
  • With Cloudflare: Request → Tokyo edge server (10ms latency)
  • 20x faster response time

Impact: Global latency reduced from 200ms to 20ms average. 95% of requests served from edge cache. Bandwidth costs reduced by 80%.

The Challenge: E-commerce platform serves product images, videos, and static assets globally. High bandwidth costs and slow load times hurt sales.

The Solution: Amazon CloudFront CDN:

  • Product images: Cached at edge for weeks (rarely change)
  • Product videos: Cached at edge for days
  • Static assets: CSS, JS cached forever (versioned URLs)

Example: Product page with 20 images:

  • Without CDN: 20 requests × 100ms = 2 seconds load time
  • With CloudFront: 20 requests × 10ms = 200ms load time
  • 10x faster page load

Impact: Page load time reduced by 80%. Conversion rate increased by 15% (faster pages = more sales). Bandwidth costs reduced by 70%.

The Challenge: Netflix streams billions of hours of video daily. Video files are huge (GBs), and streaming from origin would be slow and expensive.

The Solution: Netflix uses CDN for video delivery:

  • Popular content: Cached at edge locations worldwide
  • Regional caching: Popular shows cached in each region
  • Adaptive streaming: Different quality versions cached

Example: User in Brazil streams “Stranger Things”:

  • Without CDN: Stream from US origin (high latency, buffering)
  • With CDN: Stream from Brazil edge server (low latency, smooth playback)
  • Instant playback, no buffering

Impact: 99% of video streams served from edge cache. Reduced origin bandwidth by 95%. Smooth playback for users worldwide.

The Challenge: GitHub serves millions of repositories with static assets (images, documentation, releases). High traffic, need fast delivery.

The Solution: GitHub uses CDN for static assets:

  • Repository assets: Cached at edge (images, documentation)
  • Release files: Cached at edge (binaries, archives)
  • Versioned URLs: /releases/v1.2.3/app.zip (cache forever)

Example: User downloads release file:

  • Without CDN: Download from origin (slow for distant users)
  • With CDN: Download from nearest edge (fast for all users)
  • 5x faster download speed

Impact: Download speeds increased by 5x globally. Reduced origin server load by 90%. Better experience for international users.

The Challenge: YouTube serves billions of video thumbnails daily. Thumbnails are small but accessed frequently.

The Solution: YouTube uses CDN for thumbnails:

  • Thumbnails: Cached at edge locations worldwide
  • Long TTL: Thumbnails cached for weeks (rarely change)
  • Geographic distribution: Served from nearest edge

Example: User browses YouTube homepage:

  • 20 thumbnails per page
  • Without CDN: 20 requests × 50ms = 1 second
  • With CDN: 20 requests × 5ms = 100ms
  • 10x faster thumbnail loading

Impact: Homepage load time reduced by 80%. 99% of thumbnail requests served from edge. Reduced origin bandwidth by 95%.

The Challenge: Spotify serves music metadata (album art, artist info, playlists) globally. Metadata changes infrequently but needs fast access.

The Solution: Spotify uses CDN for metadata:

  • Album art: Cached at edge for weeks
  • Artist profiles: Cached at edge for days
  • Playlist metadata: Cached at edge for hours

Example: User opens Spotify app:

  • Loads 50 album covers
  • Without CDN: 50 requests × 100ms = 5 seconds
  • With CDN: 50 requests × 10ms = 500ms
  • 10x faster app load

Impact: App load time reduced by 80%. 95% of metadata requests served from edge. Smooth experience for global users.

The Challenge: Facebook serves billions of images and videos daily. High bandwidth costs and slow load times hurt user experience.

The Solution: Facebook uses CDN for media:

  • User photos: Cached at edge for days
  • Videos: Cached at edge for hours
  • Profile pictures: Cached at edge for weeks

Example: User scrolls Facebook feed:

  • 20 images per screen
  • Without CDN: 20 requests × 150ms = 3 seconds
  • With CDN: 20 requests × 15ms = 300ms
  • 10x faster feed loading

Impact: Feed load time reduced by 85%. 98% of media requests served from edge. Reduced bandwidth costs by 80%. Better mobile experience (saves data).



ProviderBest ForKey Features
CloudflareGeneral purposeFree tier, DDoS protection, global network
AWS CloudFrontAWS ecosystemIntegrated with S3, Lambda@Edge
FastlyDynamic contentReal-time purging, edge computing
AkamaiEnterpriseLargest network, advanced features

🌍 Geographic Latency

CDN reduces latency by caching content closer to users worldwide. 10-30x faster!

📦 Static First

Static content (images, CSS, JS) is perfect for CDN. Cache for long time.

🔧 Cache-Friendly APIs

Use proper HTTP headers, version URLs, separate cacheable from non-cacheable.

🏷️ Version URLs

Version static assets (app.v1.2.3.js) to enable long caching without invalidation.