Diagnosing Stale Content in Next.js ISR – A Step‑by‑Step Diagnostic Guide
When pages on a Next.js Jamstack site stay outdated after the configured revalidation period, pinpointing the culprit can be tricky. This guide walks through the most common ISR failures, offers a concise check‑list, and shows how to verify each step.
30 Jul 2026, 09:38 UTC

Recognizable Condition
After a configured revalidate period has elapsed, a page still shows the old version of the content. Users see stale data, and the page’s Last‑Modified header hasn’t updated.
Common Causes & Diagnostic Table
| Cause | Diagnostic Check | Fix |
|---|---|---|
| Revalidation interval not reached | Verify the revalidate value and the time since the last request | Increase revalidate or wait for the period to expire |
| Check CDN cache headers and edge function caching rules | Configure CDN to bypass cache for ISR URLs or set Cache-Control: no-store in the response |
|
Inspect CI logs for a missing next build step | Add or restore the build step in the deployment workflow | |
Review getStaticPaths and fallback flag | Set fallback: true or blocking to allow on‑demand generation |
|
Ensure the function returns props and revalidate | Correct the return object; remove notFound: true if not needed |
Ordered Diagnostic Checklist
Verify Next.js Version
ISR is available from Next.js 12.0 onward. Run
npx next --versionin the project root. If you see11.xor lower, upgrade first.Confirm Revalidation Interval
Open
next.config.jsor the page’sgetStaticPropsand locaterevalidate. Example:export async function getStaticProps() { const data = await fetchData(); return { props: { data }, revalidate: 60, // seconds }; }Use
curl -I https://example.com/pageto check theCache‑Controlheader. It should includemax-age=60orstale-while-revalidatedepending on your CDN config.Inspect
getStaticPropsReturnEnsure the returned object contains both
propsandrevalidate. A missingpropsor anotFound: truewill stop regeneration.Check CDN Edge Cache Settings
Many hosting providers cache ISR responses at the edge. Verify that the CDN’s cache rules allow
stale-while-revalidateor that the edge function setsCache-Control: no-store. In Vercel, for example, navigate to the Edge Functions tab and confirm thecachePolicyis set tono-cachefor ISR routes.Validate Dynamic Route Fallback
For pages generated with
getStaticPaths, thefallbackflag must betrueorblockingto allow ISR to create new pages on demand. Iffallback: false, only pre‑built paths can be regenerated.Review Build & Deployment Logs
Check your CI pipeline for a
next buildstep. If the workflow uses cached artifacts, ISR may not trigger. Look for logs similar to:Building project… ✔ Built 12 static pages ✔ Built 1 dynamic page with ISRTest Manual Revalidation
Create an API route to trigger revalidation:
// pages/api/revalidate.js export default async function handler(req, res) { const { secret, path } = req.query; if (secret !== process.env.REVALIDATE_SECRET) { return res.status(401).json({ message: 'Invalid secret' }); } try { await res.revalidate(path || '/'); return res.json({ revalidated: true }); } catch (err) { return res.status(500).json({ error: err.message }); } }Trigger it with:
curl -X POST "https://example.com/api/revalidate?secret=xyz&path=/page"After a successful response, reload the page and verify that the content has updated within seconds.
Escalation Criteria
- All checks above pass, but stale content persists.
- CDN logs show the ISR response is being cached with
no-storestill not honored. - Manual revalidation fails with a 500 error.
In these cases, open an issue with your hosting provider or the Next.js community. Provide the next.config.js, the API route code, and the relevant log snippets.
Limitations & Practical Verification
ISR relies on the underlying serverless runtime and CDN. If the CDN’s caching policy is not correctly configured, the page may never hit the ISR function. Always verify that the x-nextjs-revalidate header appears in the response when a revalidation occurs. If it’s missing, the page was served from cache.
When using edge functions, remember that they run in a separate environment; changes to next.config.js may require a full redeploy.
Example: Stale Content Scenario
Below is a minimal setup that demonstrates a stale page and the steps to fix it.
// next.config.js
module.exports = {
reactStrictMode: true,
// Ensure ISR is enabled
experimental: {
runtime: 'edge',
},
};
// pages/blog/[slug].js
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug);
return {
props: { post },
revalidate: 30, // 30‑second interval
};
}
export async function getStaticPaths() {
const posts = await fetchAllPosts();
return {
paths: posts.map((p) => ({ params: { slug: p.slug } })),
fallback: true, // enable ISR for new posts
};
}
// pages/api/revalidate.js
export default async function handler(req, res) {
const { secret, path } = req.query;
if (secret !== process.env.REVALIDATE_SECRET) return res.status(401).end();
try {
await res.revalidate(path || '/');
res.status(200).json({ revalidated: true });
} catch (e) {
res.status(500).json({ error: e.message });
}
}
Deploy this stack, wait 30 seconds, then refresh /blog/first-post. If the content is still old, run the diagnostic checklist above.
Summary
Stale content in a Next.js ISR site usually points to one of five common misconfigurations: the revalidation interval hasn’t elapsed, edge caching is overriding ISR, the build process is skipping next build, dynamic routes lack a proper fallback, or getStaticProps is returning an incorrect object. By following the ordered diagnostic checklist, verifying headers, and testing manual revalidation, you can quickly isolate the problem and apply the appropriate fix.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.