Redis & Advanced Caching

CDN and Edge Caching

20 min Lesson 18 of 30

CDN and Edge Caching

Content Delivery Networks (CDNs) cache content at edge locations worldwide, serving users from the nearest server. This dramatically reduces latency and improves page load times globally.

What is a CDN?

A CDN is a distributed network of servers that cache and deliver content from locations geographically closer to users. Instead of every request traveling to your origin server, the CDN serves cached content from edge servers.

Benefits: Reduced latency (50-90% faster), lower bandwidth costs, DDoS protection, and improved scalability.

How CDNs Work

When a user requests content, the CDN edge server checks its cache. If the content exists and is fresh, it's served immediately. If not, the CDN fetches from origin, caches it, and serves it.

User Request Flow:\n1. User requests https://cdn.example.com/logo.png\n2. DNS resolves to nearest CDN edge server\n3. Edge server checks cache\n4. If cached: serve immediately (cache HIT)\n5. If not cached: fetch from origin, cache, serve (cache MISS)\n6. Subsequent requests: served from cache

Popular CDN Providers

Major CDN providers offer global edge networks with different features and pricing models.

Top CDNs: Cloudflare (200+ locations, free tier), AWS CloudFront (450+ locations), Fastly (developer-friendly), Akamai (enterprise), BunnyCDN (affordable).

Cloudflare CDN Setup

Cloudflare provides free CDN services with automatic caching of static assets.

// Cloudflare automatically caches:\n// - Images (.jpg, .png, .gif, .webp)\n// - CSS and JavaScript files\n// - Fonts (.woff, .woff2, .ttf)\n// - Videos and audio files\n\n// Custom cache rules via Page Rules:\n// Cache Level: Standard, Aggressive, or Bypass\n// Edge Cache TTL: Override origin cache headers\n// Browser Cache TTL: Control client-side caching\n\n// Example Page Rule:\n// URL: *.example.com/assets/*\n// Settings:\n//   Cache Level: Cache Everything\n//   Edge Cache TTL: 1 month\n//   Browser Cache TTL: 4 hours

AWS CloudFront Setup

CloudFront integrates with AWS services and provides advanced caching controls.

// CloudFront distribution configuration\n{\n  "Origins": [{\n    "DomainName": "origin.example.com",\n    "Id": "myOrigin"\n  }],\n  "DefaultCacheBehavior": {\n    "TargetOriginId": "myOrigin",\n    "ViewerProtocolPolicy": "redirect-to-https",\n    "AllowedMethods": ["GET", "HEAD", "OPTIONS"],\n    "CachedMethods": ["GET", "HEAD"],\n    "ForwardedValues": {\n      "QueryString": false,\n      "Cookies": { "Forward": "none" }\n    },\n    "MinTTL": 0,\n    "DefaultTTL": 86400,  // 1 day\n    "MaxTTL": 31536000     // 1 year\n  }\n}
Tip: Use different cache behaviors for different URL patterns (static assets vs API endpoints).

Cache Headers for CDN

HTTP cache headers control how CDNs and browsers cache content. Set appropriate headers on your origin server.

// Express.js cache headers\napp.use('/assets', (req, res, next) => {\n  // Cache static assets for 1 year\n  res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n  next();\n});\n\napp.use('/api', (req, res, next) => {\n  // Don't cache API responses\n  res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');\n  next();\n});\n\n// Vary header for content negotiation\nres.setHeader('Vary', 'Accept-Encoding, Accept-Language');\n\n// ETag for validation\nres.setHeader('ETag', generateETag(content));

Cache-Control Directives

Understanding Cache-Control directives is crucial for proper CDN caching.

// Cache-Control directives:\n\n// public - Can be cached by CDN and browsers\nCache-Control: public, max-age=3600\n\n// private - Only browser cache, not CDN\nCache-Control: private, max-age=3600\n\n// no-cache - Must revalidate before serving\nCache-Control: no-cache\n\n// no-store - Never cache (sensitive data)\nCache-Control: no-store\n\n// immutable - Content never changes (versioned assets)\nCache-Control: public, max-age=31536000, immutable\n\n// s-maxage - CDN cache TTL (overrides max-age for CDN)\nCache-Control: public, max-age=3600, s-maxage=86400
Best Practice: Use versioned URLs for static assets (app.v123.js) and set immutable with long max-age.

Origin Shielding

Origin shielding adds an extra caching layer between edge servers and origin to reduce origin load.

// Without origin shielding:\nEdge Server 1 (cache miss) → Origin\nEdge Server 2 (cache miss) → Origin\nEdge Server 3 (cache miss) → Origin\n// 3 origin requests for same content\n\n// With origin shielding:\nEdge Server 1 (cache miss) → Shield Server (cache miss) → Origin\nEdge Server 2 (cache miss) → Shield Server (cache hit)\nEdge Server 3 (cache miss) → Shield Server (cache hit)\n// Only 1 origin request\n\n// CloudFront origin shield configuration:\n{\n  "OriginShield": {\n    "Enabled": true,\n    "OriginShieldRegion": "us-east-1"\n  }\n}

Purging CDN Cache

Invalidate cached content when you deploy updates or need to remove stale data.

// Cloudflare API purge\nconst cloudflare = require('cloudflare')({\n  token: 'your-api-token'\n});\n\n// Purge specific files\nawait cloudflare.zones.purgeCache(zoneId, {\n  files: [\n    'https://example.com/style.css',\n    'https://example.com/app.js'\n  ]\n});\n\n// Purge by cache tag\nawait cloudflare.zones.purgeCache(zoneId, {\n  tags: ['product-images']\n});\n\n// Purge everything (use sparingly!)\nawait cloudflare.zones.purgeCache(zoneId, {\n  purge_everything: true\n});
// AWS CloudFront invalidation\nconst AWS = require('aws-sdk');\nconst cloudfront = new AWS.CloudFront();\n\nconst params = {\n  DistributionId: 'E1234567890ABC',\n  InvalidationBatch: {\n    CallerReference: Date.now().toString(),\n    Paths: {\n      Quantity: 2,\n      Items: [\n        '/assets/style.css',\n        '/assets/app.js'\n      ]\n    }\n  }\n};\n\nawait cloudfront.createInvalidation(params).promise();
Warning: CDN purges can be expensive and slow. Use versioned URLs instead of frequent purges.

Static vs Dynamic Caching

Different content types require different caching strategies.

// Static content (images, CSS, JS):\n// - Long cache times (1 month to 1 year)\n// - Use versioned filenames (app.v123.js)\n// - Cache-Control: public, max-age=31536000, immutable\napp.use('/static', express.static('public', {\n  maxAge: '1y',\n  immutable: true\n}));\n\n// Dynamic content (HTML pages):\n// - Short cache times (5 minutes to 1 hour)\n// - Use ETag for validation\n// - Cache-Control: public, max-age=300, must-revalidate\napp.get('/blog/:slug', async (req, res) => {\n  const post = await getPost(req.params.slug);\n  const etag = generateETag(post);\n  \n  if (req.get('If-None-Match') === etag) {\n    return res.status(304).end();\n  }\n  \n  res.set({\n    'Cache-Control': 'public, max-age=300, must-revalidate',\n    'ETag': etag\n  });\n  res.render('post', { post });\n});

Edge Computing with Cloudflare Workers

Run code at the edge to customize caching behavior and content delivery.

// Cloudflare Worker example\naddEventListener('fetch', event => {\n  event.respondWith(handleRequest(event.request));\n});\n\nasync function handleRequest(request) {\n  const url = new URL(request.url);\n  \n  // Custom caching logic\n  if (url.pathname.startsWith('/api/')) {\n    // Don't cache API\n    return fetch(request);\n  }\n  \n  // Check cache\n  const cache = caches.default;\n  let response = await cache.match(request);\n  \n  if (!response) {\n    // Fetch from origin\n    response = await fetch(request);\n    \n    // Cache for 1 hour\n    const headers = new Headers(response.headers);\n    headers.set('Cache-Control', 'public, max-age=3600');\n    \n    response = new Response(response.body, {\n      status: response.status,\n      headers\n    });\n    \n    event.waitUntil(cache.put(request, response.clone()));\n  }\n  \n  return response;\n}
Tip: Use edge computing for A/B testing, geolocation-based routing, and personalized content delivery.

Monitoring CDN Performance

Track cache hit rates, bandwidth usage, and performance metrics.

// Key CDN metrics:\n\n// Cache Hit Rate: (cache hits / total requests) * 100\n// Target: >90% for static assets, >70% for dynamic content\n\n// Origin Shield Hit Rate: Shield cache hits / shield requests\n// Target: >80%\n\n// Bandwidth Saved: Origin bandwidth vs total bandwidth\n// Good CDN should save 60-90% bandwidth\n\n// P95 Response Time: 95th percentile request latency\n// Target: <100ms globally\n\n// Cache Miss Rate: Failed cache lookups\n// High miss rate indicates caching issues
Exercise: Set up a CDN for a web application. Configure cache rules for static assets (1 year) and HTML pages (5 minutes). Implement origin shield to reduce origin load. Add cache headers to your application. Deploy an update using versioned asset URLs (style.v2.css) without purging. Monitor cache hit rates and optimize based on metrics.