Caching & ISR
How Vercel caches your app — CDN caching, Incremental Static Regeneration, the Data Cache, and time-based vs on-demand revalidation.
Caching is what makes a Vercel app fast and cheap to run: responses are served from the edge instead of recomputed on every request. This page covers the layers involved and how to keep cached content fresh.
The cache layers
Vercel has more than one cache, and they serve different things:
| Layer | Stores | Scope |
|---|---|---|
| CDN cache | Full HTTP responses (HTML, assets) | Every edge region |
| ISR cache | Pre-rendered page output, in durable storage | One function region (+ CDN) |
| Data Cache | Results of individual fetch calls inside functions | Project-wide, durable |
The CDN cache and Data Cache are different layers: the CDN stores whole responses, while the Data Cache stores the results of data fetches your functions make. They work together — a fully static page is served via ISR/CDN, while a page that fetches data benefits from the Data Cache underneath.
Incremental Static Regeneration (ISR)
ISR is the headline caching strategy. It combines the speed of static content with the freshness of server rendering, following the stale-while-revalidate pattern: a visitor gets the fast cached response immediately, and Vercel regenerates the page in the background — either on a timer or when you trigger it.
What you get with ISR on Vercel:
- Durable storage. The ISR cache lives alongside your function region and persists content for 31 days, or until you revalidate it. Each deployment has its own cache.
- Request collapsing. When many requests hit the same uncached path at once, Vercel collapses them into a single function invocation per region, protecting your backend during spikes.
- Globally consistent purging. When you revalidate, all regional caches update within about 300ms, and Vercel purges the HTML and data payloads together so users never see a half-updated page.
- Selective pre-rendering. Pre-render popular pages at build time and generate the rest on demand on first request.
If revalidation fails (a network error, a non-cacheable status code, or a function error), Vercel keeps serving the existing cached content and retries shortly after rather than showing an error.
Time-based revalidation
Set an interval and the page regenerates at most that often. In the Next.js App Router:
// app/blog/[id]/page.tsx
export const revalidate = 3600; // seconds — regenerate at most once an hourVercel recommends a high interval (an hour rather than a second). Revalidating too frequently — writing to the cache almost as often as you read from it — is cost-inefficient and defeats the purpose.
On-demand revalidation
Purge a route or tag exactly when the underlying data changes (a CMS publish, a webhook), instead of waiting for a timer. Tag-based revalidation is the recommended approach for granular control:
// tag a fetch
const res = await fetch('https://api.example.com/products', {
next: { tags: ['products'] },
});
// later, in a Server Action or Route Handler, when data changes:
import { revalidateTag } from 'next/cache';
revalidateTag('products');A common, robust pattern is on-demand revalidation for instant updates plus a long time-based revalidate as a safety net.
Observing cache behavior
The x-nextjs-cache response header tells you what happened: HIT (served from cache), STALE (served from cache while revalidating in the background), MISS (rendered fresh), or REVALIDATED (regenerated on demand).
A note on cost
CDN reads and writes are free, but ISR reads and writes hit durable storage and are billed regionally, and ISR functions incur invocation usage when they revalidate. Two practical tips: set your default function region near your data source to cut cache-miss latency, and avoid non-deterministic output (new Date(), Math.random()) in cached pages — it makes every revalidation look like a change and forces an ISR write. See Pricing & plans for how usage is billed.