Deciding When to Use Next.js ISR Instead of Full Rebuilds or SSR
A decision guide for Jamstack teams choosing between full static rebuilds, Next.js ISR, and SSR for public pages that tolerate short staleness.
04 Sept 2026, 02:32 UTC

Decision and constraints
Problem: a Jamstack site with hundreds of public pages takes longer to rebuild every time content changes. A full static rebuild is simple, but build time grows with page count, and every editorial publish triggers a new deployment. Per-request server-side rendering keeps content fresh but sacrifices CDN edge caching and increases per-request cost. The decision is whether to use Incremental Static Regeneration (ISR) for public pages that can tolerate short staleness.
Constraints: content is public and not personalized, the hosting target is Vercel or a self-hosted Node server running Next.js, and the team can accept a brief stale-content window. ISR is not appropriate for user-specific pages, legal disclosures, financial data, or inventory counts where accuracy must be immediate.
Compare supported options
| Option | Best for | Trade-off |
|---|---|---|
| Full static export | Small sites, infrequent changes | Rebuild time grows linearly; every change deploys the whole site |
| ISR with time-based revalidate | Public pages needing near-real-time updates without full rebuilds | Eventual consistency; visitors may see stale content until the window elapses |
| On-demand ISR revalidation | Headless CMS publish events that should update specific routes immediately | Requires a protected webhook secret; exposed tokens allow unauthorized regeneration |
| Per-request SSR | Pages that must always be fresh | Higher latency and cost; loses edge caching unless paired with framework-specific caching |
Trade-offs to accept before enabling ISR
ISR caches pages after the first request. Subsequent requests within the revalidation window receive the cached version. When the window expires, the next request receives the stale page while the server regenerates it in the background. This means two visitors can briefly see different versions of the same page.
Platform behavior differs. Vercel supports ISR natively. Self-hosted Next.js requires a Node server (next start) and may not apply edge caching identically. The App Router and Pages Router use different revalidation APIs, so the example below targets the Pages Router; check your framework version before adapting it to App Router.
ISR caches are shared unless you segment by cookies or headers. Do not use it for authentication-dependent content.
Implementation: time-based ISR in Next.js Pages Router
Run these commands in a local terminal or CI build environment. You need write access to the repository and permission to run next build. Replace placeholders such as MY_SECRET_TOKEN with values from your secret manager; do not commit secrets.
// pages/blog/[slug].js
import { fetchPost } from '@/lib/content';
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug);
return {
props: { post },
// Regenerate at most once every 60 seconds.
revalidate: 60,
};
}
export default function BlogPost({ post }) {
return {post.content};
}
The revalidate: 60 setting tells Next.js to cache the page for up to 60 seconds. After that, the next request receives the stale page while the server regenerates it in the background.
On-demand revalidation from a CMS webhook
For faster updates, expose a protected API route that the headless CMS calls on publish:
// pages/api/revalidate.js
export default async function handler(req, res) {
if (req.query.secret !== process.env.REVALIDATION_SECRET) {
return res.status(401).json({ message: 'Invalid token' });
}
try {
await res.unstable_revalidate('/blog/hello-world');
return res.json({ revalidated: true });
} catch (err) {
return res.status(500).json({ message: 'Revalidation failed' });
}
}
Configure the CMS webhook to call this route with the secret query parameter. The route regenerates only the specified path without deploying a new build.
Validation
- Run
next buildand thennext startlocally to simulate production behavior. - Request the page twice with
curl -I https://localhost:3000/blog/hello-world. - Inspect the
x-nextjs-cacheandAgeresponse headers. Expect MISS on the first request and HIT on the second within the revalidation window. - Trigger the on-demand webhook and request the page again. Confirm the updated content appears without a new deployment.
Risks: next start is intended for local production simulation, not long-term production hosting. On-demand revalidation tokens must rotate regularly; an exposed token allows cache poisoning or unauthorized regeneration. If your compliance requirements prohibit stale content, do not enable ISR on those routes.
Rollback
Changing revalidate or adding the revalidation API route changes application state. To roll back, revert the revalidate value to a longer window or remove the API route, then redeploy the previous build. Verify the rollback by checking that x-nextjs-cache returns HIT and that the previous content remains until the next scheduled regeneration.
Practical check before production
Compare build times and deployment frequency between full static export and ISR in a staging environment with the same content volume. Confirm your hosting provider documents ISR support and cache TTL defaults. If self-hosting, verify that your Node server and any upstream proxy preserve the cache headers Next.js emits.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.