3 min read
On this page

CDN & Edge Caching

Overview

A Content Delivery Network (CDN) is a geographically distributed network of servers that caches content close to end users. CDNs reduce latency by serving requests from the nearest edge location instead of routing every request back to the origin server. For global applications, a CDN is not optional infrastructure -- it is a fundamental architectural component.

CDN Architecture

Without CDN:
  User in Tokyo -> Origin server in Virginia (200ms round trip)
  Every request crosses the Pacific Ocean.

With CDN:
  User in Tokyo -> CDN edge in Tokyo (5ms round trip)
  Edge serves cached content locally.
  Only cache misses reach the origin server.

CDN topology:
  Edge locations (Points of Presence / PoPs):
    Hundreds of locations worldwide.
    Serve cached content directly to users.
    First layer that receives user requests.

  Regional edge caches (mid-tier):
    Fewer locations, larger capacity.
    Reduce load on origin by consolidating edge misses.
    Not all CDN providers have this tier.

  Origin server:
    Your actual server (or origin shield).
    Only handles requests that miss all cache layers.

Request flow:
  User -> Nearest Edge PoP
    Cache hit -> Serve from edge (fastest)
    Cache miss -> Regional edge cache
      Cache hit -> Serve from regional (fast)
      Cache miss -> Origin server
        Response flows back through each layer, populating caches

How Users Reach the Nearest Edge

DNS-based routing:
  User queries cdn.example.com
  CDN's authoritative DNS returns the IP of the nearest edge
  Based on: user's DNS resolver IP, latency measurements, server health

Anycast routing:
  Multiple edge servers share the same IP address.
  Network routing (BGP) directs packets to the nearest server.
  Used by: Cloudflare, Google Cloud CDN

Combination:
  DNS returns anycast IP groups.
  Anycast routes within the group to the closest server.
  Most large CDNs use a hybrid approach.

Cache-Control Headers

HTTP cache-control headers tell CDNs (and browsers) how to cache responses. Getting these right is the most important aspect of CDN configuration.

Key directives:

Cache-Control: public, max-age=86400
  CDN and browser can cache for 24 hours.
  Use for: static assets (images, CSS, JS with content hashes)

Cache-Control: private, max-age=300
  Browser can cache for 5 minutes, but CDN must not cache.
  Use for: user-specific data (profile page, dashboard)

Cache-Control: no-cache
  Can be cached, but must revalidate with origin before serving.
  Use for: content that changes unpredictably but benefits from caching

Cache-Control: no-store
  Must not be cached anywhere. Every request goes to origin.
  Use for: sensitive data (banking, medical records)

Cache-Control: s-maxage=3600, max-age=60
  CDN caches for 1 hour, browser caches for 1 minute.
  s-maxage overrides max-age for shared caches (CDN).
  Use for: public content where CDN staleness is acceptable

Cache-Control: stale-while-revalidate=60
  Serve stale content while refreshing in the background.
  If cached content is expired by up to 60 seconds,
  serve it immediately and refresh asynchronously.
  Use for: content where brief staleness is acceptable

Cache-Control: stale-if-error=86400
  If origin is unavailable, serve stale content for up to 24 hours.
  Better to show slightly old content than an error page.
  Use for: resilience during origin outages

ETag & Conditional Requests

ETag (Entity Tag): A fingerprint of the resource content.

First request:
  GET /style.css
  Response: 200 OK
            ETag: "abc123"
            Cache-Control: no-cache

Subsequent request:
  GET /style.css
  If-None-Match: "abc123"

  If content unchanged:
    Response: 304 Not Modified (no body transferred)
    CDN and browser use cached version.

  If content changed:
    Response: 200 OK
              ETag: "def456"
              (new content in body)

Benefit: Validates freshness without transferring the full response.
Saves bandwidth when content rarely changes.

Edge Computing

Edge computing moves application logic to CDN edge locations, executing code closer to users instead of at a central origin.

Traditional CDN: Cache and serve static content.
Edge computing: Execute code at the edge to generate dynamic responses.

Use cases:
  - Authentication and authorization at the edge
  - A/B testing (select variant at edge, no origin round trip)
  - Geolocation-based content (local pricing, language selection)
  - Request routing and load balancing
  - Image optimization and resizing
  - API response transformation
  - Bot detection and security filtering

Platforms:
  Cloudflare Workers: V8 isolates, global deployment in seconds
  AWS Lambda@Edge / CloudFront Functions: Run at CloudFront PoPs
  Fastly Compute: WebAssembly-based edge compute
  Vercel Edge Functions: Built on Cloudflare Workers
  Deno Deploy: Global V8-based edge runtime

Limitations:
  - Limited execution time (typically 1-50ms for edge, longer for workers)
  - Limited memory and CPU
  - No persistent local storage (must call external services)
  - Cold start considerations (varies by platform)
  - Debugging is harder (distributed across hundreds of locations)

Real-World Edge Computing

Cloudflare runs their entire Workers platform on edge compute, serving billions of requests daily with sub-millisecond cold starts.

Netflix uses edge computing for API routing, A/B test assignment, and request authentication at their Open Connect CDN locations.

Shopify uses edge computing to serve storefront pages with personalization, reducing time-to-first-byte significantly compared to origin-based rendering.

Origin Shielding

Origin shielding adds a caching layer between CDN edge nodes and your origin server, consolidating cache misses.

The Problem

Without origin shielding:
  100 CDN edge locations worldwide.
  Popular item expires at all edges simultaneously.
  100 concurrent requests hit your origin server.
  Each edge independently fetches from origin on cache miss.

  Worse: If edges have different TTL expiration times,
  your origin receives a steady stream of cache miss requests
  from different edges throughout the TTL period.

How Origin Shielding Works

With origin shielding:
  100 CDN edge locations worldwide.
  1 origin shield server (e.g., in Virginia, near your origin).

  Edge miss -> Origin shield (single point of consolidation)
    Shield hit -> Return to edge (origin not contacted)
    Shield miss -> Fetch from origin (only 1 request)

  Result: Your origin sees at most 1 request per TTL period
  instead of up to 100.

Configuration:
  Most CDNs offer this as a setting:
  - CloudFront: Enable "Origin Shield" and select a region
  - Fastly: "Shielding" with a designated shield PoP
  - Cloudflare: "Tiered Caching" (automatic)

Benefits:
  - Reduces origin load by 90%+ for popular content
  - Increases overall cache hit ratio
  - Protects origin from traffic spikes
  - Reduces origin bandwidth costs

Cache Invalidation at Scale

Invalidating cached content across a global CDN is one of the hardest operational challenges.

Invalidation Methods

Method 1: TTL expiration
  Set appropriate Cache-Control max-age.
  Content expires naturally after TTL.
  No active invalidation needed.
  Con: Cannot force immediate update.

Method 2: Purge by URL
  CDN API call to purge a specific URL.
  Propagates to all edge locations.
  Most CDNs complete purge in seconds to minutes.

  Example:
  POST /purge
  { "url": "https://cdn.example.com/images/logo.png" }

Method 3: Purge by tag/key
  Tag content when caching, purge all content with a tag.
  Useful for invalidating all assets related to a product or page.

  Tag on cache: Surrogate-Key: product-123 homepage
  Purge: POST /purge { "tag": "product-123" }
  All content tagged "product-123" is purged globally.

  Supported by: Fastly (Surrogate-Key), CloudFront (cache tags),
  Cloudflare (cache tags in Enterprise)

Method 4: Versioned URLs (cache busting)
  Include a version or content hash in the URL.
  /css/style.v3.css or /css/style.abc123.css
  New version = new URL = CDN fetches from origin.
  Old version remains cached but is no longer referenced.

  Best practice: Use content hashes in asset URLs.
  Build tools (Webpack, Vite) do this automatically.
  Combine with long max-age (1 year) for immutable assets.

Invalidation Strategy by Content Type

Static assets (CSS, JS, images):
  Versioned URLs with content hashes.
  Cache-Control: public, max-age=31536000, immutable
  Never invalidate. Deploy new versions with new URLs.

HTML pages:
  Short TTL or no-cache with ETag validation.
  Cache-Control: public, s-maxage=60, stale-while-revalidate=30
  References versioned asset URLs.

API responses:
  Vary by authorization, accept headers.
  Cache-Control: public, s-maxage=300
  Purge by tag when underlying data changes.

User-specific content:
  Cache-Control: private (browser only, not CDN)
  Or: Do not cache at all (no-store).

CDN Selection & Real-World Usage

Major CDN providers:

Cloudflare:
  Free tier available. Strong security features (DDoS, WAF).
  Workers for edge compute. Anycast network.
  Used by: 20%+ of all websites.

AWS CloudFront:
  Tight integration with AWS services.
  Lambda@Edge and CloudFront Functions.
  Used by: Slack, Spotify, PBS.

Fastly:
  Instant purge (150ms global). Powerful VCL configuration.
  Compute@Edge (WebAssembly). Strong API response caching.
  Used by: GitHub, The New York Times, Stripe.

Akamai:
  Largest network (4,000+ PoPs). Enterprise-focused.
  Advanced security and performance features.
  Used by: Major banks, media companies, game publishers.

Google Cloud CDN:
  Integrated with GCP. Uses Google's global network.
  Used by: Companies on Google Cloud Platform.

Real-World CDN Architecture Examples

Netflix operates Open Connect, their own CDN. They place cache servers inside ISP networks, so popular content is served from within the ISP's own infrastructure. During peak hours, Open Connect serves over 100 Tbps of traffic.

GitHub uses Fastly for serving repository content, pages, and API responses. Fastly's instant purge capability means code pushes are visible within seconds globally.

Shopify serves millions of storefronts through Cloudflare, using edge computing for personalization and caching for product pages, with origin shielding to protect backend infrastructure.

Common Pitfalls

  • Caching authenticated responses on CDN: Using Cache-Control: public for responses that contain user-specific data serves one user's data to another. Always use private or no-store for authenticated content.
  • Missing Vary header: If responses differ by header (Accept-Encoding, Authorization), the CDN must know to cache separate versions. Missing Vary headers cause wrong content to be served.
  • Purge as the primary strategy: If you rely on purging for every update, you are fighting the CDN instead of working with it. Use versioned URLs for assets and short TTLs for dynamic content.
  • Not testing cache behavior: Use curl -I to inspect response headers. Verify Cache-Control, ETag, and CDN-specific headers (X-Cache, CF-Cache-Status) are correct.
  • Ignoring cache key configuration: By default, CDNs may include query parameters in the cache key. /page?utm_source=twitter and /page?utm_source=email are cached as separate entries unless you configure the CDN to ignore marketing parameters.
  • Origin not handling load after cache miss storm: When a popular item expires or is purged, the origin must handle the resulting spike. Origin shielding and stale-while-revalidate help.

Key Takeaways

  • CDNs reduce latency by serving content from edge locations near users. For global applications, a CDN is essential infrastructure.
  • Cache-Control headers are the primary mechanism for controlling CDN behavior. Invest time in getting them right for each content type.
  • Use versioned URLs for static assets (long TTL, never purge) and short TTLs or validation (ETag) for dynamic content.
  • Origin shielding consolidates cache misses, protecting your origin from traffic spikes and reducing origin load by 90% or more.
  • Edge computing moves application logic to CDN locations, enabling personalization, A/B testing, and authentication without origin round trips.
  • Cache invalidation at scale requires a strategy: versioned URLs for assets, tag-based purging for related content, and TTL expiration as the baseline.