Using Next.js Incremental Static Regeneration to Keep Blog Posts Fresh Without Full Rebuilds
Learn how Next.js Incremental Static Regeneration lets you serve blog posts instantly while updating them in the background, with a concrete code example and header‑verification steps.
02 Feb 2026, 22:17 UTC

The problem: fast updates vs. costly rebuilds
A content‑driven blog needs to show new posts almost instantly, but rebuilding the entire site on every change wastes CPU and delays deployment. If you rely on client‑side rendering, SEO suffers; if you pre‑render everything at build time, a single typo forces a full redeploy. The goal is to serve stale pages immediately while updating them in the background.
Thesis: ISR gives you static speed with on‑demand freshness
Next.js Incremental Static Regeneration (ISR) lets you generate a page at build time and mark it for automatic regeneration after a set interval. When a request hits a stale page, Next.js returns the cached version immediately and triggers a background rebuild. The result is low latency for readers and bounded server work for publishers.
How ISR works in the Pages Router
In pages/blog/[slug].js you export getStaticProps with a revalidate field (seconds). Next.js treats the page as static until the revalidate time passes, at which point the next request triggers regeneration.
// pages/blog/[slug].js
import { notFound } from 'next/navigation'
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug) // your data layer
if (!post) return notFound()
return {
props: { post },
revalidate: 60, // regenerate at most once per minute
}
}
export default function Post({ post }) {
return (
{post.title}
)
}
When revalidate: 60 is set, the first request after a minute of inactivity will see the old HTML while Next.js fetches fresh data and builds a new version. Subsequent requests get the fresh page.
How ISR works in the App Router
The App Router uses route‑segment configs and generateStaticParams to decide which URLs are pre‑rendered. You can add a revalidate export or call revalidatePath from a webhook.
// app/blog/[slug]/page.js
import { notFound } from 'next/navigation'
export const revalidate = 60 // seconds
export async function generateStaticParams() {
const posts = await fetchAllPosts() // [{ slug: 'first-post' }, ...]
return posts.map(p => ({ slug: p.slug }))
}
export default async function Page({ params }) {
const post = await fetchPost(params.slug)
if (!post) return notFound()
return (
{post.title}
)
}
If you prefer to trigger regeneration from your CMS, call await revalidatePath('/blog/my-new-post') inside an API route or webhook handler.
Worked example: verifying ISR headers
After deploying the above code, you can check that the browser/CDN receives a Cache‑Control header with stale‑while‑revalidate matching your revalidate value.
# Run from your local machine or CI
curl -I https://example.com/blog/my-post
Expected output (values will vary):
HTTP/2 200
cache-control: public, max-age=0, s-maxage=60, stale-while-revalidate=60
age: 12
...
The s-maxage and stale-while-revalidate values should equal the number you set in revalidate. The Age header shows how long the current copy has been cached.
You can also view the page source and look for a JSON‑LD block that Next.js injects during regeneration; its dateModified field updates when a new build finishes.
Trade‑offs and limits
- Setting
revalidate: 0or omitting it forces a regeneration on every request, turning ISR into costly server‑side rendering and potentially overwhelming your origin under traffic spikes. - generateStaticParams must return an array. Returning
undefinedornull yields zero static pages, a frequent pitfall when moving from the Pages Router to the App Router. - Edge runtime considerations. In the App Router,
revalidateworks at the edge only if the route stays in the edge runtime. Usingdynamicimports, certain middleware, or Node‑specific APIs forces a Node.js server; you must explicitly setruntime: 'nodejs'innext.config.jsto avoid unexpected fallback. - Cache‑header propagation. Some CDNs or edge middleware may strip or alter the
stale‑while‑revalidatedirective. Always verify headers in your staging environment before relying on ISR for production traffic.
Actionable checklist
- Choose the router that matches your project (Pages for simple migrations, App for new features).
- Add
revalidate: <seconds>(e.g., 60) to yourgetStaticPropsor route export. - Ensure
generateStaticParamsreturns an array of slug objects. - Deploy, then run
curl -I <URL>to confirmCache‑Controlincludesstale‑while‑revalidatewith the expected value. - Monitor origin logs; you should see regeneration spikes only when the revalidate window expires, not on every request.
- If you use edge middleware, test that the header survives the edge path; otherwise, add
runtime: 'nodejs'tonext.config.js.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.