CDN Explained: What It Is, How It Works, and How to Use It in Next.js
A CDN (Content Delivery Network) is a global network of servers that cache and serve your static assets โ JS, CSS, images, fonts โ from a location close to the user.
Without a CDN, every user hits your origin server (wherever it's hosted).
With a CDN, they hit the nearest edge node instead.
๐ How It Works
- User requests
/logo.png - CDN checks its edge cache
- Cache hit โ served immediately from edge
- Cache miss โ CDN fetches from your origin, caches it, serves it
Next request from any user near that edge? Instant.
๐ฆ What Gets Cached?
| Asset type | Cached by CDN? |
|---|---|
| JS / CSS bundles | โ |
| Images / fonts | โ |
| HTML (static) | โ |
| API responses | โ ๏ธ optional |
| Dynamic SSR pages | โ ๏ธ optional |
โก Why It Matters for Frontend
- Lower latency โ assets served from 50ms away, not 300ms
- Less load on your server โ CDN absorbs most traffic
- Better Core Web Vitals โ faster LCP, less layout shift
- Global scale โ same performance in Tokyo as in London
๐ง CDN in Next.js
Next.js is CDN-ready out of the box. Here's what gets cached automatically:
Static assets in /public
Served with long-lived cache headers automatically.
next/image
Images are optimized and served via CDN edge with proper Cache-Control.
Static pages (SSG)
Pages generated at build time are cached at the CDN edge.
โ๏ธ Configuration
1. Custom CDN with assetPrefix
If you're using your own CDN (Cloudflare, CloudFront, etc.):
// next.config.js
module.exports = {
assetPrefix: 'https://cdn.yourdomain.com',
}
Next.js will now load all /_next/static/ assets from your CDN URL.
2. Cache-Control headers
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/static/(.*)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
max-age=31536000โ cache for 1 yearimmutableโ browser won't revalidate even on hard refresh
3. Per-fetch CDN caching (App Router)
// cached for 1 hour at the CDN edge
const data = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 },
})
4. Page-level revalidation (ISR)
// app/blog/page.tsx
export const revalidate = 60 // revalidate every 60 seconds
CDN serves the cached page, Next.js regenerates it in the background when stale.
5. Force static caching
export const dynamic = 'force-static'
Tells Next.js (and the CDN) to never recompute โ serve the static version always.
๐ง Cache-Control Cheat Sheet
| Header value | Meaning |
|---|---|
public, max-age=31536000, immutable | Cache forever (versioned assets) |
public, s-maxage=3600 | CDN cache for 1 hour |
no-store | Never cache |
stale-while-revalidate=60 | Serve stale, refresh in bg |
โจ Final Takeaway
A CDN puts your assets next to your users. Next.js handles most of it automatically โ configure
assetPrefixfor custom CDNs, and userevalidateto control how long pages stay cached at the edge.