Dynamic Page Delivery: Next.js Incremental Static Regeneration (ISR) at Scale
How to use Next.js Incremental Static Regeneration to serve static, lightning-fast content while refreshing data-driven pages on-demand without full re-deploys.
Kazi Shariful Islam
Full Stack Developer • Technical Case Study
Introduction#
Serving high-traffic blogs or dynamic real-estate indexes requires an intricate balance between load speeds and content freshness. Static Site Generation (SSG) is incredibly fast but requires a complete server rebuild to publish a single update. Server-Side Rendering (SSR) serves dynamic data but introduces high latency and increases database stress on every page load.
Next.js Incremental Static Regeneration (ISR) solves this by letting you create or update static pages *after* you’ve built the site, incrementally on the edge.
Time-Based Revalidation#
To update a specific static route automatically at a set interval, we use the revalidate property. If a request arrives after the revalidation timer has expired, Next.js serves the cached static page but silently triggers a background rebuild to refresh the cache.
// app/blog/page.tsx
import { getPosts } from '@/lib/api';
// Revalidate this page every 60 seconds (1 minute)
export const revalidate = 60;
export default async function BlogPage() {
const posts = await getPosts();
return (
<main className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-bold">Latest Industry Logs</h1>
<div className="grid gap-6 mt-6">
{posts.map(post => (
<article key={post.id} className="border-b pb-4">
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
</main>
);
}
On-Demand Revalidation via Webhook#
Time-based revalidation is useful but can lead to stale data during active intervals. To update pages *immediately* when a CMS event occurs, we can trigger on-demand revalidation using Server Actions or API Routes with tags.
First, tag your fetch request:
const res = await fetch('https://api.example.com/posts', {
next: { tags: ['blog-posts'] }
});
Then, trigger revalidation from your webhook route:
// app/api/revalidate/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { revalidateTag } from 'next/cache';
export async function POST(req: NextRequest) {
const secret = req.nextUrl.searchParams.get('secret');
if (secret !== process.env.REVALIDATION_SECRET) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
}
// Clear cache for any fetch request tagged with 'blog-posts'
revalidateTag('blog-posts');
return NextResponse.json({ revalidated: true, now: Date.now() });
}
Production Metrics#
By replacing Server-Side Rendering (SSR) with ISR for our high-traffic lookup portals:
- TTFB (Time to First Byte) dropped by 80%: Delivering immediate static pages from the CDN edge.
- Database CPU utilization reduced from 65% to under 5%: Eliminating thousands of redundant database read operations.
Kazi Shariful Islam
Full Stack Developer
Passionate about high-performance React architectures, WebAssembly on the edge, and zero-downtime distributed deployments.
Related Technical Logs
Boosting React Response Speeds by 30% with TanStack Query
A deep architectural dive on setting up robust stale times, garbage collection, and localized key mutations to eliminate duplicate server load.
How We Scaled Shopify Apps Using Custom Shopify Functions
An engineering review on writing low-latency discount and cart-transform logics in Node.js running directly on Shopify Edge servers.