What is Incremental Static Regeneration?
Static generation provides exceptional performance by pre-rendering pages at build time. However, static sites face a fundamental challenge: keeping content fresh without rebuilding the entire site. Incremental Static Regeneration (ISR) solves this by allowing pages to be updated after deployment, combining the speed of static delivery with the flexibility of dynamic content.
ISR is our preferred rendering strategy for content-driven sites where freshness matters but not at the cost of performance. It enables teams to update thousands of pages instantly through simple cache invalidation, without triggering full site rebuilds or sacrificing the static delivery that users love. Our web development team specializes in implementing optimal rendering strategies for each client's unique requirements.
How ISR Works Under the Hood
When a request arrives for an ISR-cached page, Next.js first checks the cache. If the cached version exists and hasn't exceeded its revalidation period, it's served instantly from the CDN. If the cache is stale or missing, Next.js serves the stale version while triggering a background regeneration. The next visitor receives the updated page once regeneration completes.
This background regeneration pattern ensures users never wait for page generation, even during content updates. The cache serves stale content momentarily while fresh content regenerates in parallel. For most content sites, serving slightly stale data for a few seconds poses no problem--and users appreciate the instant page loads that result.
The Request Flow
- Cache Check: Next.js checks edge cache for the requested page
- Serve or Regenerate: Valid cache serves instantly; stale or missing cache triggers regeneration
- Background Build: While users see cached content, Next.js regenerates in the background
- Cache Update: Once complete, the updated page replaces the stale version
- Next Request: Subsequent visitors receive the freshly generated page
1export const revalidate = 60 // Revalidate every 60 seconds2 3export default async function ProductPage({ params }: { params: { slug: string } }) {4 const product = await fetch(`https://api.example.com/products/${params.slug}`, {5 next: { revalidate: 60 }6 }).then(res => res.json())7 8 return (9 <div>10 <h1>{product.name}</h1>11 <p>{product.description}</p>12 <span>${product.price}</span>13 </div>14 )15}Time-Based Revalidation
Time-based revalidation is the simplest ISR pattern. You specify how often pages should regenerate, and Next.js handles cache invalidation automatically. This approach works well for content with predictable update cycles--daily blog posts, hourly reports, or weekly product updates.
Setting Revalidation Intervals
The revalidate value can be set at multiple levels. Fetch calls inherit the segment's revalidate value unless overridden, and individual fetches can specify their own intervals for mixed freshness requirements.
// Different revalidation for different data
const product = await fetch(`https://api.example.com/products/${slug}`, {
next: { revalidate: 3600 } // Product data: 1 hour
}).then(res => res.json())
const inventory = await fetch(`https://api.example.com/inventory/${slug}`, {
next: { revalidate: 60 } // Inventory: 1 minute
}).then(res => res.json())
Use Cases
- News sites: 5-15 minute revalidation for timely content
- Marketing pages: 1-hour+ intervals for stable content
- Analytics dashboards: 60-second intervals for near-real-time data
On-Demand Revalidation
On-demand revalidation provides precise control over cache invalidation. Instead of waiting for a time interval to pass, you can trigger updates immediately when content changes using revalidatePath and revalidateTag.
Using Cache Tags
Tag your fetches for targeted invalidation:
// Fetch with tags
const products = await fetch('https://api.example.com/products', {
next: { tags: ['products'] }
}).then(res => res.json())
API Route for Webhooks
Create an API route to handle webhook triggers from your CMS:
// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache'
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
const secret = request.nextUrl.searchParams.get('secret')
if (secret !== process.env.REVALIDATION_SECRET) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 })
}
// Invalidate all pages using the 'products' cache tag
revalidateTag('products')
return NextResponse.json({ revalidated: true, now: Date.now() })
}
Why choose Incremental Static Regeneration
Instant Page Loads
Pages served from edge cache eliminate server processing time
Fresh Content
On-demand invalidation ensures updates appear within seconds
Reduced Build Times
Only critical pages built at deploy; others generate on-demand
Cost Efficiency
Fewer server requests and faster builds reduce infrastructure costs
Global Scale
Edge caching serves users from locations near them
Simple Workflow
Content updates don't require developer deployment coordination
ISR vs SSG vs SSR: Choosing the Right Strategy
Understanding where ISR fits in the rendering spectrum helps you make informed architecture decisions.
Static Site Generation (SSG)
Pure static generation builds all pages at deploy time. Pages are pre-rendered HTML served directly from CDN--no server processing, no database queries. This provides the fastest possible performance but requires full rebuilds for any content changes. Our guide on Static Generation (SSG) covers this approach in detail.
Best for: Documentation sites, landing pages, content that rarely changes
Server-Side Rendering (SSR)
SSR generates pages on each request. Every visitor triggers fresh data fetching and template rendering, ensuring always-current content but with increased latency and server load.
Best for: Real-time dashboards, personalized content, authenticated user experiences
Incremental Static Regeneration (ISR)
ISR combines static performance with dynamic flexibility. Pages are cached at edge locations and updated in background when content changes. First visitors after updates may trigger regeneration; subsequent visitors receive cached content instantly.
Best for: ECommerce product pages, blogs, news sites, content-heavy marketing sites
| Strategy | Performance | Freshness | Build Time | Best Use Case |
|---|---|---|---|---|
| SSG | Instant | Low | High | Static content |
| SSR | Variable | Instant | N/A | Real-time data |
| ISR | Fast | High | Low | Dynamic content |
ISR in Production
60s
Minimum revalidation interval
100ms
Typical edge cache response
Best Practices for ISR
Tag Naming Conventions
Establish consistent tagging conventions to make invalidation predictable and maintainable:
- Content type tags:
'posts','products','users' - Context tags:
'posts-dashboard','posts-feed' - Temporal tags:
'breaking-news'for time-sensitive invalidation
Graceful Degradation
Design pages to handle stale data gracefully:
- Display "in stock" or "limited availability" rather than exact inventory counts
- Show pricing ranges or note that prices may vary at checkout
- Use relative time indicators ("updated 5 minutes ago") instead of absolute timestamps
Monitoring and Debugging
Use response headers to understand cache behavior:
x-nextjs-cache: HIT // Served from cache
x-nextjs-cache: MISS // First visit, generated fresh
x-nextjs-cache: STALE // Served stale while regenerating
High MISS rates on production pages may indicate overly short revalidation periods or caching issues requiring investigation. Fast page loads achieved through ISR also improve search engine rankings, making performance optimization a key part of your SEO strategy.
Frequently Asked Questions
Sources
- Next.js Official Documentation - ISR - Core implementation details, API references, and App Router patterns
- Vercel ISR Documentation - Production deployment insights and caching behavior
- Contentful ISR Guide - CMS integration patterns and practical examples