Skip to content

Cdn

Chapter 20: Content Delivery Networks (CDN)

Section titled “Chapter 20: Content Delivery Networks (CDN)”

A CDN (Content Delivery Network) is a geographically distributed network of servers that delivers content to users based on their physical location.

The CDN Difference
=================
Without CDN:
─────────────────────
User in Tokyo Origin Server in NYC
│ │
│ Cross-pacific request │
│ ~150-200ms latency │
│ ──────────────────────────────▶│
│ │
│ Response travels back │
│ ~150-200ms latency │
│ ◀──────────────────────────────│
Total: ~300-400ms
─────────────────────────────────────────
With CDN:
─────────────────────
User in Tokyo CDN Edge in Tokyo
│ │
│ Local request │
│ ~5-20ms latency │
│ ──────────────────────────────▶│
│ │ (Cache hit!)
│ Instant response │
│ ◀──────────────────────────────│
Total: ~5-20ms (10-20x faster!)
MetricWithout CDNWith CDNImprovement
Latency300ms20ms15x faster
Origin load100%<10%10x reduction
Availability99.5%99.99%Higher uptime
Bandwidth costs$10,000$2,00080% savings

CDN Request Flow
===============
┌─────────────────────────────────────────────────────────────┐
│ Step 1: User Requests Content │
│ ─────────────────────────────────────────────────────────│
│ │
│ User clicks: https://example.com/image.jpg │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 2: DNS Resolution │
│ ─────────────────────────────────────────────────────────│
│ │
│ DNS returns: CDN edge server IP (closest to user) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Global DNS Server │ │
│ │ │ │
│ │ example.com → 203.0.113.50 (Tokyo edge) │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 3: Edge Server Check │
│ ─────────────────────────────────────────────────────────│
│ │
│ Is image.jpg in cache? │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ CDN Edge Server (Tokyo) │ │
│ │ │ │
│ │ Cache: [image.jpg] ✅ FOUND! │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 4: Cache Hit (If cached) │
│ ─────────────────────────────────────────────────────────│
│ │
│ Return cached content to user │
│ │
│ Total time: ~10ms! │
│ │
└─────────────────────────────────────────────────────────────┘
─────────────────────────────────────────────────────────
Cache Miss Flow (First request):
───────────────────────────────
┌─────────────────────────────────────────────────────────────┐
│ If Not Cached: │
│ │
│ CDN Edge → Origin Server (fetch content) │
│ │ │
│ │ Content returned │
│ ▼ │
│ CDN Edge → Cache content │
│ │ │
│ ▼ │
│ CDN Edge → Return to user │
│ │
│ (First request slower, subsequent requests fast!) │
└─────────────────────────────────────────────────────────────┘
CDN Architecture Overview
========================
┌─────────────────────────────────────────────────────────────┐
│ Users │
│ (Mobile, Desktop, TV) │
└────────────────────────────┬────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ DNS Service │
│ (GeoDNS - routes to nearest edge) │
└────────────────────────────┬────────────────────────────────┘
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Edge │ │ Edge │ │ Edge │
│ (Tokyo) │ │ (NYC) │ │ (London) │
│ │ │ │ │ │
│ POP: 50 │ │ POP: 50 │ │ POP: 50 │
│ Servers │ │ Servers │ │ Servers │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└─────────────────────┼─────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Origin Servers │
│ (Your application servers) │
└─────────────────────────────────────────────────────────────┘
POP (Point of Presence):
───────────────────────
Each POP has 50+ servers
Strategically placed in 100+ cities worldwide

CategoryExamplesTypical TTL
Static ImagesJPG, PNG, WebP, GIF1 day - 1 year
CSS/JSStylesheets, JavaScript1 day - 1 year
VideosOn-demand, streaming chunks1 hour - 1 day
DocumentsPDF, eBooks1 week
API ResponsesCached API data1 min - 1 hour
FontsWOFF2, WOFF, TTF1 year
Static Content
=============
• Never changes (or changes rarely)
• Same for all users
• Perfect for CDN caching
• Examples: logos, images, CSS, JS
─────────────────────────────────────────
Dynamic Content
==============
• Changes per request
• Personalized per user
• Usually NOT cached (or very short TTL)
• Examples: API responses, user profiles
─────────────────────────────────────────
Semi-Static (Cacheable with care)
=================================
• Changes occasionally
• Can cache with short TTL
• Examples:
- Homepage (cache 1-5 min)
- Product catalog (cache 5-15 min)

HTTP Cache Headers
=================
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control: max-age=3600 │
│ ─────────────────────────────────────────────────────────│
│ │
│ Cache can serve this for 3600 seconds (1 hour) │
│ │
│ After 1 hour: Must revalidate with origin │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control: s-maxage=3600 │
│ ─────────────────────────────────────────────────────────│
│ │
│ Only shared caches (CDN) respect this │
│ Browser ignores it │
│ │
│ Use: When you want different TTL for CDN vs browser │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control: no-cache │
│ ─────────────────────────────────────────────────────────│
│ │
│ Always validate with origin before serving │
│ (Check if changed, use cache if identical) │
│ │
│ Use: Sensitive/important content │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control: no-store │
│ ─────────────────────────────────────────────────────────│
│ │
│ Never cache this content │
│ │
│ Use: Private data, API responses │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control: private │
│ ─────────────────────────────────────────────────────────│
│ │
│ Only browser can cache, not CDN │
│ │
│ Use: Personalized content │
└─────────────────────────────────────────────────────────────┘
ETag (Entity Tag)
================
How it works:
─────────────────────
Request 1:
─────────
GET /image.jpg
Response:
HTTP 200 OK
ETag: "abc123"
Content: [image data]
Request 2 (later):
─────────────────
GET /image.jpg
If-None-Match: "abc123"
Response:
(If unchanged)
HTTP 304 Not Modified
[No body - uses cached copy!]
─────────────────────────────────────────
Benefits:
─────────
• Saves bandwidth
• Faster response (304 vs 200)
• Still validates freshness
Cache Invalidation Methods
=========================
1. TTL Expiration
─────────────────
Content automatically expires after TTL
Simple, but can't force immediate update
2. Manual Purge
─────────────────
API call to CDN to clear specific content
CloudFront: CreateInvalidation
Cloudflare: Purge Cache
Example:
aws cloudfront create-invalidation \
--distribution-id ABC123 \
--paths "/images/*"
3. Versioned URLs (Best Practice!)
─────────────────────────────────
Old: /js/app.js (changes break users)
New: /js/app.v1.js (immutable)
/js/app.v2.js (new version)
Benefits:
• Never need to purge
• Instant rollout
• Easy rollback
• Cache forever
4. Cache Tags
─────────────────
Tag content and purge by tag
Response: Cache-Tag: product, images, homepage
Purge: Purge by tag "product"

ProviderStrengthsBest For
CloudFrontAWS integration, Lambda@EdgeAWS users
CloudflareSecurity, Workers, Free tierEveryone
AkamaiEnterprise scale, reliabilityLarge enterprises
FastlyReal-time purging, VCLDynamic content
Google Cloud CDNGoogle infrastructureGCP users
BunnyNetAffordable, simpleBudget projects
# CloudFront Distribution
Resources:
MyDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
DefaultRootObject: index.html
Origins:
- Id: MyOrigin
DomainName: myapp.elb.us-east-1.amazonaws.com
CustomOriginConfig:
OriginProtocolPolicy: https-only
DefaultCacheBehavior:
TargetOriginId: MyOrigin
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: 658327ea-f89d-4fab-a...
# Caching headers
MinTTL: 0
DefaultTTL: 86400
MaxTTL: 31536000
# Compress
Compress: true
# Allowed methods
AllowedMethods:
- GET
- HEAD
- OPTIONS
CachedMethods:
- GET
- HEAD
# Origin shield (additional caching layer)
OriginShield:
Enabled: true
OriginShieldRegion: us-east-1
# Custom error pages
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 404
ResponsePagePath: /404.html

Modern CDNs go beyond caching - they can run code at the edge!

Edge Computing vs Traditional CDN
=================================
Traditional CDN:
─────────────────────
• Cache and serve static content
• Read-only operations
Edge Computing:
─────────────────────
• Run code at edge locations
• Modify requests/responses
• Authentication/authorization
• A/B testing
• Personalization
• Request routing
─────────────────────────────────────────
Use Cases:
─────────────────────
1. Edge Authentication
───────────────────
Verify JWT at edge before routing to origin
User → Edge → Validate Token → Origin (if valid)
2. A/B Testing
───────────────────
Split traffic at edge based on cookies/headers
User → Edge → Assign variant → Origin A or B
3. Request Transformation
───────────────────
Modify headers, rewrite URLs
/old-path → /new-path (at edge)
4. Personalization
───────────────────
Customize content based on user data
User location → Personalized content from edge
// Cloudflare Worker - Edge Authentication
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
// Check for valid token at edge
const token = request.headers.get('Authorization')
if (!token || !isValid(token)) {
return new Response('Unauthorized', { status: 401 })
}
// Fetch from origin (authenticated request)
const response = await fetch(request)
// Add custom headers
response.headers.set('X-Edge-Worker', 'true')
return response
}
function isValid(token) {
// Verify JWT or API key at edge
// Much faster than origin verification
}

CDN Best Practices Checklist
============================
✓ Cache static assets with long TTL (1 year)
✓ Use versioned URLs for JS/CSS
✓ Enable compression (Brotli > Gzip)
✓ Enable HTTP/2 or HTTP/3
✓ Use HTTPS everywhere
✓ Set proper Cache-Control headers
✓ Configure origin shield for better caching
✓ Monitor cache hit ratio (target >95%)
✓ Use signed URLs for private content
✓ Enable Cloudflare/AWS Shield for DDoS protection
CDN Performance Tips
===================
1. PRELOADING
─────────────────────
Pre-populate cache before launch
Example: Pre-cache all product images
2. REGIONAL ORIGINS
─────────────────────
Place origins near major user bases
US East + US West + Europe + Asia
3. COMPRESSION
─────────────────────
Enable Brotli (better than Gzip)
20% smaller files than Gzip
4. HTTP/2 & HTTP/3
─────────────────────
Faster than HTTP/1.1
Multiplexing, header compression
5. OPTIMIZE IMAGES
─────────────────────
Use WebP/AVIF
Serve responsive images (srcset)

  1. CDN - Geographically distributed servers for fast content delivery
  2. Reduce latency - Serve from nearest edge location (10-20x faster)
  3. Cache static content - Images, videos, CSS, JS with long TTL
  4. Cache invalidation - Versioned URLs (best), manual purge, TTL
  5. Edge computing - Run code at edge for auth, personalization
  6. Security - DDoS protection, WAF included with most CDNs

Next: Chapter 21: Circuit Breaker Pattern