Edge Computing, CDNs & Caching

CDN Fundamentals: Why Every Site Needs One

A Content Delivery Network distributes your content across a global network of edge servers, serving users from the nearest point of presence (PoP) instead of your origin server. The impact is dramatic: a user in Tokyo requesting a page from a US-East origin pays ~200ms in round-trip latency per request; with a CDN PoP in Tokyo, that drops to ~5–20ms. Since a typical page load involves dozens of requests (HTML, CSS, JS, images, fonts), CDN caching can easily shave 1–3 seconds off total load time.

Every website benefits from a CDN — even small personal sites. Free tiers from Cloudflare (unlimited bandwidth), Vercel, and Netlify make CDN usage accessible to all. For production applications, choose a CDN based on: PoP count and geographic distribution (Cloudflare has 330+, AWS CloudFront 600+), protocol support (HTTP/3, Early Hints, Brotli/Zstd), edge compute capabilities, and the API/configuration model that fits your workflow.

The major CDN providers in 2026: Cloudflare (broadest free tier, Workers ecosystem, 330+ PoPs), AWS CloudFront (deepest AWS integration, 600+ PoPs, Lambda@Edge), Akamai (enterprise-grade, largest legacy network), Fastly (developer-focused, Compute@Edge with Wasm), Vercel (Next.js-optimized, built on Cloudflare), Netlify (Jamstack-focused, Deno-powered Edge Functions).

Resources:

Edge Functions: Code at the CDN Layer

Edge computing has evolved beyond static caching into a full compute platform. Edge functions execute server-side code at the CDN PoP closest to the user, reducing Time to First Byte (TTFB) by 60–80% compared to origin rendering — from 200–800ms down to 20–50ms. The three dominant platforms have converged on V8 isolate runtimes:

Cloudflare Workers — 330+ PoPs, sub-5ms cold starts via V8 isolates, 50ms CPU time (Unbound plan allows more). Integrated ecosystem: KV (globally replicated key-value store), R2 (S3-compatible object storage, zero egress fees), D1 (SQLite at the edge), Durable Objects (strongly consistent stateful edge), Workers AI (AI inference at the edge). Framework support for Hono, Remix, SvelteKit, Astro.

Vercel Edge Functions — runs on Cloudflare’s network with tight Next.js integration. Adding export const runtime = 'edge' to any route or middleware deploys it globally. Edge Config (5MB globally replicated KV) for feature flags and A/B test assignment. Vercel KV (Upstash Redis) for more complex data patterns. Vercel’s Fluid Compute technology uses bytecode caching and predictive warming for near-zero cold starts.

Deno Deploy — built on the Deno runtime (V8-based, web-standards-first), strong TypeScript and npm compatibility since Deno 2. Sub-10ms cold starts, Wasm support for Rust/Go edge logic. Secure-by-default permission model.

What to run at the edge: authentication checks, A/B test assignment, geolocation routing, feature flag evaluation, static personalization (locale, currency), redirects and URL rewrites, bot detection, request/response header manipulation. What to keep at origin: database writes, complex business logic, payment processing, long-running computations, third-party API calls with rate limits.

The stale-while-revalidate pattern is the ideal edge caching strategy: serve the cached response immediately (instant TTFB), trigger a background revalidation to refresh the cache, and serve the fresh response to the next request. Users get speed (no origin round-trip) and freshness (content updates within minutes).

Resources:

HTTP Caching: The Most Underutilized Performance Tool

HTTP caching is the single most effective performance mechanism on the web — a properly cached response costs zero network latency, zero server compute, and zero bandwidth. Yet Jono Alderson’s analysis finds that many sites have broken or absent cache headers. Understanding Cache-Control directives is essential.

Caching Strategy by Resource Type

Immutable static assets (JS/CSS with content hashes, versioned images): Cache aggressively forever. The hash in the filename (e.g., app.9f2d1a.js) guarantees uniqueness — when the content changes, the filename changes, and the browser fetches a new URL.

Cache-Control: public, max-age=31536000, immutable

immutable tells the browser: “don’t even revalidate this on a page refresh — the content will never change at this URL.” This eliminates revalidation round-trips that waste time on fingerprinted assets.

HTML pages and API responses (dynamic, must be relatively fresh): Use short max-age with stale-while-revalidate for the best speed/freshness balance:

Cache-Control: public, max-age=60, stale-while-revalidate=600, stale-if-error=86400

This serves cached HTML for 60 seconds (instant response), allows stale content for up to 10 minutes while revalidating in the background, and falls back to stale content for up to 24 hours if the origin is down. For CDNs, use s-maxage to set a longer edge cache TTL than the browser TTL:

Cache-Control: public, max-age=0, s-maxage=3600, stale-while-revalidate=86400

This tells browsers to always revalidate (max-age=0) but lets the CDN serve cached content for 1 hour, with stale-while-revalidate extending that up to 24 hours during background refresh.

Personalized/authenticated content: Must not be stored in shared caches:

Cache-Control: private, no-cache, must-revalidate

private keeps it out of CDN caches. no-cache forces revalidation every time. must-revalidate prevents serving stale content even during network issues.

Sensitive data (banking, medical, PII): Must not be stored anywhere:

Cache-Control: no-store

Revalidation: ETags and Conditional Requests

When a cached response expires, the browser sends a conditional request with If-None-Match (ETag) or If-Modified-Since headers. If the resource hasn’t changed, the server responds with 304 Not Modified — just headers, no body — saving the full download while confirming freshness. Configure your server to generate strong ETags for all cacheable resources.

Common Caching Mistakes

  • No cache headers at all: browsers apply heuristic caching based on Last-Modified, which is unpredictable. Always set explicit Cache-Control.
  • Short max-age on fingerprinted assets: If your build tool adds content hashes to filenames, use max-age=31536000, immutable. The hash is your cache-busting mechanism.
  • no-cache when you mean no-store: no-cache still caches but revalidates every request. no-store prevents caching entirely. Know the difference.
  • Missing Vary: Accept-Encoding: If you serve Brotli/gzip/zstd based on Accept-Encoding, the Vary header tells caches to store separate versions per encoding. Without it, a gzip user might get a Brotli-encoded response from cache.

Resources:

Service Worker Caching: Offline-First Strategies

Service workers provide a programmable cache layer between your application and the network, enabling offline support, instant repeat-visit loads, and fine-grained control over caching strategies. The major patterns (implementable via Workbox or manually):

Cache First (offline-first): Check the cache first; only hit the network if the resource isn’t cached. Ideal for static assets (fonts, images, immutable JS/CSS). Once cached, these resources load in ~0ms on repeat visits.

Network First (freshness-first): Try the network; fall back to cache if offline or slow. Ideal for HTML pages and API responses where freshness matters but offline access is still valuable.

Stale-While-Revalidate: Serve from cache immediately, fetch a fresh copy from the network in the background, and update the cache for the next request. The best general-purpose strategy — instant response with eventual freshness.

Cache Only / Network Only: Extremes for content that should never touch the network (pre-cached critical shell) or should never be cached (real-time data).

For font caching specifically (as mentioned in Section 15), pre-caching WOFF2 files at service worker install time gives repeat visitors ~0ms font loading — an easy win that few sites implement.

Resources:

Edge Databases and Global Data

The “edge” was historically limited to static caching because databases lived in a single region. Running edge functions that needed data still required a round-trip to the origin database, negating latency gains. Edge databases solve this:

Cloudflare D1 — SQLite replicated to edge PoPs, read replicas globally with single-region writes. Ideal for read-heavy workloads (product catalogs, CMS content, feature flags).

Turso (libSQL) — distributed SQLite with embedded replicas, where a lightweight database replica runs alongside your edge function. Sub-millisecond reads with automatic replication from the primary.

PlanetScale (Vitess-based MySQL) — regional read replicas with connection pooling designed for serverless. Their “Boost” feature caches query results at the edge.

Neon (Serverless Postgres) — branching, autoscaling, and a serverless driver optimized for edge functions with connection pooling.

KV stores: Cloudflare KV, Vercel Edge Config, and Upstash Redis provide sub-millisecond reads for configuration data, feature flags, session tokens, and other small key-value data. Write propagation is eventually consistent (seconds to minutes), making them unsuitable for data requiring strong consistency but perfect for read-heavy patterns.

The pattern: store data that’s read 1000× more often than it’s written at the edge (product info, configuration, translations). Keep write-heavy data (orders, user accounts, transactions) at the origin with strong consistency guarantees.

Resources: