The Static Site That Thinks It's Dynamic
Incremental Static Regeneration gives you most of the speed of static and most of the freshness of server rendering — if you respect its edges.
Static generation is fast because it does the work once, at build time, and serves the same bytes to everyone after. The catch is obvious: what happens when the content changes and you don't want to rebuild the whole site?
Stale-while-revalidate, for pages
Incremental Static Regeneration answers this by serving the last built version of a page while regenerating it in the background, on a schedule or on demand.
export const revalidate = 3600; // seconds
export default async function Page() {
const data = await getData();
return <Article data={data} />;
}The first request after the window expires gets the stale page instantly, and triggers a rebuild for the next visitor. Nobody waits on a cold render.
The edge cases that bite
- On-demand revalidation needs a trigger. If your CMS publishes a post, something has to call
revalidatePath— it doesn't happen automatically just because the data changed. - Personalization breaks the model. ISR caches one version of a page. The moment you need per-user content, you're back to dynamic rendering for that route.
- Time-based revalidation is a queue, not a promise. Under high traffic, many requests can land in the stale window simultaneously; make sure your regeneration is idempotent.
Used well, ISR is close to a free lunch for content-heavy sites. Used carelessly, it just moves the "why is this page out of date" bug report from your database team to your frontend team.
More posts
How Postgres Indexes Actually Work
A deep dive into B-tree internals, and why a sequential scan sometimes beats an index you were sure would help.
Why We Moved Off REST
GraphQL solved a real problem for our mobile clients, but it introduced a few we didn't see coming.