Static-site generation (SSG) gives you blazing-fast pages, but the moment your data changes you need a full rebuild… unless you use Incremental Static Regeneration (ISR). ISR lets a page stay static and quietly refresh in the background—no global rebuild, no slow users. Below is a 2025-focused guide that covers how ISR works in both the Pages Router and the newer App Router, shows on-demand revalidation, and finishes with best-practice tips.
1. What problem does ISR solve?
-
SSG → great performance, stale quickly.
-
SSR (or RSC “force-dynamic”) → always fresh, slower TTFB under load.
-
ISR sits between: serve a cached HTML file instantly, then — at a schedule you pick or on-demand — rebuild that single page in the background. Users never see the rebuild. nextjs.org
2. How ISR works under the hood
-
First request after a build returns the pre-rendered HTML.
-
Revalidation clock starts (e.g., 60 s).
-
After the revalidation window expires, the next request triggers a background regeneration while still getting the stale HTML (stale-while-revalidate).
-
Once the new HTML finishes, Vercel (or your host) swaps it in; future requests get the fresh page. nextjs.org
3. Using ISR in the Pages Router (/pages
)
3.1 Timed revalidation (revalidate
)
fallback: 'blocking'
shows nothing until the first HTML is ready, avoiding an empty shell. ryanschiang.com
3.2 On-demand ISR (Build-free)
Need instant refresh (e.g., when an editor clicks “Publish”)? Hit an API route that calls res.revalidate('/blog/my-slug')
:
Now a CMS webhook can POST to /api/revalidate?secret=...&path=/blog/my-slug
. geeksforgeeks.org
4. Using ISR in the App Router (/app
)
App-Router pages are static by default. You enable ISR with the revalidate
option on fetch or by exporting a revalidate
number.
4.1 Page-wide revalidate
4.2 Tag-based on-demand ISR (Next 14)
Next 14 lets you group pages by cache tags and revalidate them together, without hard-coding paths:
Great for multi-locale or multi-tenant sites. dev.toemirbalic.com
5. ISR + Edge Functions (2025 status)
-
Pages Router ISR runs in Node serverless, not Edge.
-
App Router pages delivered from the Edge can still regenerate in a regional worker; the new HTML is globally propagated via Vercel’s cache. This “Edge-delivered, Node-regenerated” combo landed in early 2025. emirbalic.com
6. Practical patterns & gotchas
Pattern | How to do it | Caveat |
---|---|---|
Selective ISR | Only pages with changing data get revalidate ; the rest stay static. dev.to |
Don’t over-refresh — static wins for speed. |
Preview drafts | Use a preview cookie and force-dynamic route to bypass ISR for logged-in editors. |
Keep preview path secret. |
Long tail pages | fallback: 'blocking' + very long revalidate (e.g., 1 day) to avoid building thousands of pages up front. |
First hit is slower. |
SEO | Search bots that respect stale-while-revalidate will eventually see fresh HTML; set sensible revalidate (< 1 day). |
N/A |
Edge + ISR | Mark page export const runtime = 'edge' (App Router) and leave revalidate on fetch. |
No filesystem access in Edge runtime. |
7. Example: Building a static product catalogue that updates hourly
Hook up a webhook from your inventory system to revalidateTag('products')
to force a refresh the moment a price changes.
8. Best practices for 2025
-
Think per-page — give marketing landing pages long TTLs, while the blog gets 1–5 min.
-
Protect revalidate tokens — keep them in env vars; rotate periodically.
-
Log regeneration times — Vercel functions show rebuild duration; watch for API bottlenecks.
-
Combine with drafts — editors preview via SSR, publish via on-demand ISR.
-
Monitor cache hit-rate — use
x-vercel-cache
header to spot forced SSR. -
Edge where it helps — global low-latency read, Node for the heavy rebuild. github.com
9. Conclusion
ISR lets you enjoy the speed of static with the flexibility of dynamic content—a must-know technique for modern Next.js sites. Whether you’re on the older Pages Router or all-in on the App Router, the 2025 workflow is straightforward: set revalidate
, tag strategically, and trigger rebuilds exactly when you need them. Happy regenerating! 🚀
Frequently Asked Questions (FAQ) — Incremental Static Regeneration (ISR)
# | Question | Quick Answer |
---|---|---|
1 | What is Incremental Static Regeneration (ISR)? | ISR is a Next.js feature that lets individual static pages regenerate in the background after a specified time or an on-demand trigger—so users get instant responses while content stays fresh. |
2 | How is ISR different from SSG and SSR? | SSG: page is built once at deploy time. SSR/RSC dynamic: page is built on every request. ISR: page is served from the cache like SSG, but selectively rebuilt on a schedule or webhook; it’s a hybrid of both worlds. |
3 | Does ISR work in both the Pages Router and App Router? | Yes. In the Pages Router you return revalidate from getStaticProps ; in the App Router you export export const revalidate = <seconds> or pass { next: { revalidate } } to fetch() . |
4 | What values can I give revalidate ? |
Any positive integer (seconds). revalidate: 60 means “rebuild at most once per minute.” Use false (or omit) for fully static, 0 for always-dynamic. |
5 | What happens during regeneration? | After the timeout, the next request receives the stale HTML, and a background rebuild starts. Once finished, the new HTML replaces the old in the cache; subsequent visitors see the fresh page. |
6 | How do I trigger ISR on demand? | Pages Router: call res.revalidate('/path') inside an API Route. App Router: import revalidatePath('/path') or revalidateTag('tag') in a Route Handler or Server Action. Hook that to a CMS webhook. |
7 | What’s the difference between revalidatePath and revalidateTag ? |
revalidatePath('/blog/my-post') refreshes one URL. revalidateTag('blog') refreshes every page whose fetch() call was tagged with next: { tags: ['blog'] } . Tags are new in Next 14+ for bulk revalidation. |
8 | Do I need to enable Vercel-specific settings for ISR? | No. ISR works out of the box on Vercel. For other hosts you need a file-system-compatible cache or the official Next.js standalone server; most major providers now support it. |
9 | Can ISR pages run on the Edge Runtime? | App-Router pages can be served from edge regions (export const runtime = 'edge' ). The regeneration itself still happens in a regional worker; the fresh HTML is then propagated worldwide. |
10 | How do I preview drafts without breaking ISR? | Serve preview mode with a cookie and bypass caching (export const dynamic = 'force-dynamic' in the App Router or fallback: 'blocking' with auth). Only editors with the cookie see unpublished content. |
11 | What’s the cost of setting revalidate too low? |
Very low values (<15 s) can cause frequent rebuilds, hitting function limits and API quotas. Tune the interval to match how often your data actually changes. |
12 | How do I know if a request is served from cache or revalidated? | Check the response header x-vercel-cache (or your host’s equivalent). Values: HIT , STALE , MISS , REVALIDATED . |
13 | Can I combine ISR with incremental static exports (next export )? |
No. next export outputs purely static HTML and disables all runtime features—use a Node or Edge deployment to get ISR. |
14 | Does ISR affect SEO? | No negative impact. Search engines receive HTML like any static site. Because rebuilds are atomic, crawlers always get a complete document—never half-rendered content. |
15 | What are common pitfalls? | Forgetting to set fallback: 'blocking' (Pages Router) can flash a loading state; using Node-only APIs in an Edge page; sending confidential revalidate tokens in query strings—keep them in env vars or headers. |