CDNs are one of the most impactful performance optimizations you can make. Learn how they work, what they cache, and when to use them.
Without a CDN, every user — regardless of location — fetches content from your origin server.
User in Mumbai → request → Server in Virginia (150ms round trip)
User in London → request → Server in Virginia (80ms round trip)
User in Tokyo → request → Server in Virginia (170ms round trip)
Physics limits how fast data can travel. A request from Mumbai to Virginia takes ~150ms just for the network round trip — before any processing.
A CDN solves this by caching content at edge nodes distributed globally.
User in Mumbai → CDN edge in Mumbai (2ms round trip)
User in London → CDN edge in London (5ms round trip)
User in Tokyo → CDN edge in Tokyo (3ms round trip)
CDN providers operate hundreds of servers (edge nodes / PoPs) distributed globally. When a user requests content:
First request (cache miss):
User → Edge Node → Origin Server → Edge Node caches → User
(150ms)
Subsequent requests (cache hit):
User → Edge Node → User
(2ms)
The CDN respects cache headers from your origin:
Cache-Control: public, max-age=86400 // cache for 24 hours
Cache-Control: no-cache // don't cache
Cache-Control: s-maxage=3600 // CDN caches for 1 hour, browser for default
If 90% of requests are served from edge cache, your origin server handles only 10% of traffic. This dramatically reduces infrastructure costs and protects against traffic spikes.
CDN edge nodes absorb attack traffic before it reaches your origin. Cloudflare, for example, has 100+ Tbps of network capacity — far more than any attacker can generate.
CDNs handle SSL/TLS at the edge. Your origin can receive plain HTTP internally, reducing CPU overhead.
CDNs automatically compress responses with gzip/Brotli, reducing transfer size by 60-80%.
When you deploy new assets, you need to invalidate the CDN cache.
Include a hash in the filename. When the file changes, the filename changes — no invalidation needed.
app.abc123.js → new deploy → app.def456.js
Webpack, Vite, and Next.js do this automatically.
/static/v2/app.js → new deploy → /static/v3/app.js
Most CDNs provide an API to purge specific URLs or paths.
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
-d '{"files": ["https://example.com/app.js"]}'CDNs can cache API responses too, but requires care:
Cache-Control: public, s-maxage=60 // CDN caches for 60 seconds
Vary: Accept-Encoding // separate cache per encoding
Good candidates: Product listings, public blog posts, search results Bad candidates: User-specific data, real-time data, write operations
| Provider | Best for | Notes |
|---|---|---|
| Cloudflare | General purpose, DDoS protection | Free tier, excellent performance |
| AWS CloudFront | AWS-native apps | Deep AWS integration |
| Fastly | Programmable CDN | Real-time purging, edge compute |
| Vercel Edge Network | Next.js apps | Built-in, zero config |
| Bunny CDN | Cost-sensitive | Cheapest per GB |
For most projects: Cloudflare (free tier is excellent) or Vercel (if already on Vercel).
Next.js on Vercel automatically uses the Vercel Edge Network:
For images, Next.js <Image> component automatically optimizes and caches via CDN.
Cache-Control headers to control what gets cached and for how long