Incremental Static Regeneration in Next.js: Serve Stale‑While‑Revalidate Blog Posts
Learn how ISR lets you serve fast static pages while updating content in the background, with a concrete getStaticProps example, trade‑offs, and verification steps.
24 Aug 2025, 00:40 UTC

The problem: fast builds vs. up‑to‑date data
Many content‑driven sites rely on Next.js' static generation because a pre‑rendered HTML file loads instantly from a CDN. The downside is that any change in the underlying data forces a full rebuild and redeploy, which can take minutes and incur extra costs.
Thesis: Incremental Static Regeneration (ISR) gives you the best of both worlds
ISR lets Next.js generate a page statically on the first request, then automatically rebuild it in the background after a user‑defined interval (the revalidate value). Visitors receive a stale‑while‑revalidate response: they see the cached version immediately, and the next request after the interval triggers a quiet regeneration.
How ISR works under the hood
When a page defines revalidate in getStaticProps, Next.js treats it as a static page with an expiration timer. The first hit renders the page, stores the HTML in the edge cache, and returns it with an Age header (or x-nextjs-revalidate) indicating how long the cache is considered fresh. After the timer expires, the next request still serves the cached copy, but Next.js spawns a server‑side render in the background. Once that render finishes, the cache is updated and subsequent visitors see the new content.
Worked example: a blog post page
// pages/posts/[slug].js
import { useRouter } from 'next/router'
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug) // your data‑fetching function
return {
props: { post },
// Revalidate at most once every 60 seconds
revalidate: 60,
}
}
export default function Post({ post }) {
const router = useRouter()
if (router.isFallback) return Loading…
return (
{post.title}
)
}
The first visitor to /posts/my‑first‑post triggers a static generation, receives the HTML, and sees an Age: 0 header. Sixty seconds later, the next request still returns the cached HTML (now with an Age close to 60) while Next.js quietly re‑fetches the post and updates the cache.
Trade‑offs and limitations
- Latency on expiry: The first request after the
revalidatewindow may experience a slight delay because the background render runs on the Node server. - Server load: Very low
revalidatevalues (e.g., 1 second) cause ISR to behave almost like server‑side rendering, increasing CPU usage and negating static performance gains. - Data source downtime: If your external API fails during a revalidation window, the stale page continues to be served until the next successful rebuild, which might be unacceptable for critical information.
These factors mean you should tune revalidate based on how often your content changes and how much traffic the page receives. A common starting point is 60 seconds for blog‑style content, adjusting upward for less‑frequent updates or downward for high‑traffic news feeds.
Actionable steps to verify and tune ISR
- Run locally: Execute
next devand request the page. Open the browser devtools Network tab, check the response headers forageorx-nextjs-revalidate. The value should increase with each reload until it hits therevalidatelimit. - Observe background work: Wait longer than the
revalidateinterval, reload the page, and watch your server console (or Vercel logs) for a log line indicating agetStaticPropsrevalidation. - Test in a preview environment: Deploy to Vercel (or another Node‑compatible host), change the data source, and confirm that the page updates automatically without a new deploy. Use the Network tab to see a 200 response with the new content after the interval.
- Monitor and adjust: Track the ratio of cache hits to background rebuilds in your analytics or logs. If you see many rebuilds relative to traffic, increase
revalidate. If users report stale content, decrease it cautiously.
Closing: make ISR part of your performance toolkit
Incremental Static Regeneration is a pragmatic compromise: you retain the speed of static CDN delivery while allowing content to stay fresh without the overhead of full rebuilds. By adding a simple revalidate field, testing the headers and logs, and adjusting the interval to match your content’s cadence, you can deliver a responsive experience that scales with traffic. Use ISR where you need occasional updates, and reserve full static generation or server‑side rendering for pages that demand real‑time data or cannot tolerate any staleness.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.