Guide
CDN explained: content delivery networks, edge caching, and performance
A content delivery network (CDN) is a distributed system of edge servers that cache copies of your website closer to visitors. Instead of every user in Tokyo, São Paulo, and Berlin pulling a 2 MB JavaScript bundle from your single origin in Virginia, they fetch it from a nearby point of presence (PoP) — often cutting round-trip latency from hundreds of milliseconds to tens. CDNs also absorb traffic spikes, terminate TLS at the edge, and provide a first line of defense against DDoS attacks. This guide explains how CDNs route requests, what they cache, how purging works, and how to pair a CDN with HTTP cache headers and modern rendering strategies.
Why CDNs exist: latency, bandwidth, and resilience
The internet is fast at the fiber level and slow at the geography level. Light travels roughly 200 km per millisecond in fiber; a user 8,000 km from your origin pays at least 80 ms each way before your server even starts work. Four round trips to establish TLS and fetch HTML can burn 300–600 ms on latency alone — a direct hit to Largest Contentful Paint (LCP).
CDNs solve three problems at once:
- Proximity — edge servers sit in hundreds of cities; most users reach one within 50 ms.
- Offload — cache hits never touch your origin, saving CPU, egress bandwidth, and database load.
- Resilience — Anycast routing and massive capacity absorb viral traffic and volumetric attacks that would overwhelm a single VPS.
For a static publisher site or a global SaaS dashboard, a CDN is often the cheapest performance win available. For a low-traffic internal admin panel accessed only from one office, it may be unnecessary overhead.
How traffic reaches the edge
When you put a site behind a CDN, you typically change DNS so
www.example.com resolves to the CDN provider instead of your
origin IP. Two routing patterns dominate:
Anycast
The CDN advertises the same IP address from many PoPs worldwide. BGP routes each client to the topologically nearest PoP. No per-region DNS gymnastics — the network does the steering. Cloudflare, Fastly, and many large providers use Anycast at the edge.
GeoDNS / latency-based DNS
The DNS server returns different edge IPs based on the resolver's location. Amazon CloudFront and some enterprise CDNs combine geo-DNS with regional edge domains. Either way, the visitor's first hop is an edge machine, not your origin.
At the edge, the CDN checks its local cache. On a cache hit, it returns the stored response immediately. On a cache miss, the edge fetches from your origin (your VPS, S3 bucket, or Kubernetes ingress), stores a copy according to cache rules, and serves it. That first miss is slower; subsequent requests from the same PoP are fast.
What CDNs cache (and what they should not)
CDNs are HTTP caches at scale. They respect
Cache-Control, ETag, and Vary headers
the same way a browser does — but with terabytes of SSD and policies you
configure in a dashboard. Think in layers:
Immutable static assets
Fingerprinted files — app.a3f9c2.js, logo.8b1d.webp
— are ideal CDN cargo. Set long max-age (a year is common) and
optional immutable. When you deploy a new build, the filename
changes; no purge needed. This pattern is standard in
SSG and ISR
pipelines where HTML references hashed assets.
HTML and API responses
Dynamic HTML is trickier. A news article can cache at the edge for minutes
with s-maxage=300 (shared cache TTL) while the browser keeps a
shorter max-age. Personalized dashboards, authenticated API
responses, and wallet-connected dApp pages usually need private, no-store
or cache keys that include a session cookie — otherwise user A sees user B's
data. When in doubt, do not cache authenticated responses at the CDN.
Cache keys and Vary
The cache key is the tuple the CDN uses to look up a stored response — typically
URL path plus selected headers. Vary: Accept-Encoding ensures gzip
and Brotli variants do not collide. Vary: Accept-Language splits
localized pages. Misconfigured keys cause subtle bugs: one PoP serves English
HTML to a French visitor because the key ignored Accept-Language.
Origin shield, tiered caching, and stale content
Popular assets might be requested from 50 edge PoPs simultaneously on a cache miss — 50 origin fetches for the same file. Origin shield adds a mid-tier cache: edges talk to a regional shield node, and only the shield talks to origin. One origin pull fans out to many edges.
Stale-while-revalidate lets the CDN serve an expired cached
copy while asynchronously refreshing from origin. Visitors see fast (slightly
old) content instead of waiting on a slow origin during a traffic spike. Pair
this with short s-maxage on HTML and longer TTLs on static
assets — the pattern described in our
HTTP caching guide.
When you must remove content immediately — a leaked file, incorrect pricing,
a security patch — you purge URLs or cache tags from the CDN
control plane. Purges propagate in seconds to minutes depending on provider.
Tag-based purging (purge tag:article-123) beats listing thousands
of asset URLs after a deploy. Plan purge APIs into your CI/CD pipeline for
non-fingerprinted resources.
TLS, HTTP/2, and compression at the edge
Most CDNs terminate TLS at the edge: the visitor gets a fast HTTP/2 or HTTP/3 connection to a nearby machine with a valid certificate, while the CDN may use a separate connection (sometimes plain HTTP on a private link) to your origin. This reduces handshake latency and lets the CDN negotiate Brotli compression even if your origin only supports gzip.
Full (strict) mode validates your origin certificate; flexible mode encrypts only the visitor-to-edge leg and is insecure for production. Always use strict validation and keep origin certificates renewed — Let's Encrypt automation on both sides is common.
HTTP/3 (QUIC) over UDP reduces head-of-line blocking on lossy mobile networks. Many CDNs enable it by default. You get multiplexed streams without managing QUIC yourself — another reason publishers route through a CDN even when origin capacity is modest.
Security: WAF, bot management, and DDoS
Hiding your origin IP behind a CDN proxy means attackers cannot bypass the edge and hammer your VPS directly — if you firewall origin to accept traffic only from the CDN's IP ranges. CDNs add:
- Volumetric DDoS absorption — SYN floods and UDP amplification die at the edge.
- Web Application Firewall (WAF) — rule sets block SQL injection, known CVE exploits, and geographic blocks.
- Bot scoring — challenge suspicious clients with JavaScript or CAPTCHA before they reach origin.
- Rate limiting — per-IP or per-API-key quotas at the edge, complementing application-level limits.
These features are not a substitute for secure application code, but they shrink the attack surface and keep your origin online when a post goes viral or a botnet probes your login form.
Choosing and configuring a CDN
Major providers — Cloudflare, Fastly, Akamai, CloudFront, Bunny, KeyCDN — differ on pricing model (per-GB egress vs flat fee), PoP density in your target regions, purge speed, edge compute (Workers, Lambda@Edge), and log/analytics depth. Evaluation checklist:
- Audience geography — match PoP maps to where your readers actually are.
- Cache hit ratio — aim for 85%+ on static assets; measure with CDN analytics.
- Origin egress cost — S3-to-CDN transfer is often free or cheap; CDN-to-user is billed.
- Purge API — required for HTML that is not fingerprinted.
- Log forwarding — ship edge logs to your observability stack for debugging cache misses.
Start simple: proxy DNS through the CDN, cache only static assets with long
TTLs, leave HTML on short s-maxage or bypass cache until you
understand personalization needs. Add WAF rules and edge workers only when
traffic justifies the complexity.
CDN + modern deployment patterns
Static sites generated at build time (Hugo, Eleventy, Vite SSG) map cleanly
onto object storage plus CDN: upload to S3/R2, point the CDN at the bucket,
set Cache-Control per file type. ISR and SSR frameworks
(Next.js, Nuxt) need origin or serverless functions behind the CDN with
cache rules per route — static pages get long edge TTL; API routes get
no-store.
For SPAs, the CDN often serves index.html with short cache TTL
and aggressive caching on JS/CSS bundles. Configure a fallback rule so
unknown paths return index.html (SPA routing) without caching
that fallback response globally with a long TTL — otherwise a new deploy's
HTML might not propagate.
Blockchain RPC endpoints and wallet RPC proxies should generally not sit on a public CDN cache — responses are user-specific and freshness-critical. Use the CDN for your marketing site and static docs; keep RPC on a dedicated low-latency path with application rate limits.
Common mistakes
- Caching HTML with
max-age=31536000and no purge plan — visitors see stale content for days. - Exposing origin IP in DNS records or outbound email headers — attackers bypass the CDN.
- Ignoring
Cache-Control: privateon authenticated pages — shared caches must not store them. - Setting
Vary: Cookieon mostly-static pages — destroys cache hit ratio. - Flexible TLS mode — encrypts only the first hop; origin traffic crosses the internet in cleartext.
- Purging individual asset URLs after every deploy instead of fingerprinting filenames.
- Expecting the CDN to fix an unoptimized 5 MB hero image — compress and resize at build time first.
Operations checklist
- DNS proxied through CDN; origin IP firewalled to CDN ranges only.
- Static assets fingerprinted with long
max-age, immutable. - HTML and APIs have explicit cache policies; authenticated routes bypass shared cache.
- Purge API wired into deploy pipeline for non-fingerprinted resources.
- TLS strict mode end-to-end; HTTP/2 or HTTP/3 enabled at edge.
- CDN analytics reviewed monthly — cache hit ratio, origin bandwidth, 4xx/5xx at edge.
- Core Web Vitals monitored in field data after CDN changes — confirm LCP improved in target regions.
Related reading
- HTTP caching explained — Cache-Control, ETags, stale-while-revalidate
- Core Web Vitals explained — LCP, INP, CLS thresholds and fixes
- TLS and HTTPS explained — certificates, handshakes, HSTS
- All Solana Garden guides