Skip to content

What Is ISR — Incremental Static Regeneration Explained

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about What Is ISR. We cover key concepts, practical examples, and best practices to help you master this topic.

Incremental Static Regeneration updates static pages after build by re-rendering individual pages in the background, combining SSG speed with fresh content.

What You'll Learn

By the end of this tutorial, you'll understand what ISR is, how it bridges SSG and SSR, the stale-while-revalidate pattern, and when to use ISR over other rendering strategies.

Why It Matters

Traditional SSG requires a full rebuild to update content. For large sites this takes hours. ISR updates only the pages that changed, keeping your site fast and fresh without sacrificing the performance benefits of static generation.

Real-World Use

An e-commerce site with 50,000 products uses ISR to update prices and inventory. When a price changes, only that product page regenerates. The rest of the site stays cached and fast, while the updated page is available within seconds.

ISR Architecture

graph LR
    A[Build Time] --> B[Pre-render pages
static HTML] A --> C[Set revalidate
time window] B --> D[CDN Cache
serves static HTML] C --> D D --> E[First visit after
revalidate window] E --> F[Serve stale page
immediately] E --> G[Background re-render] G --> H[New static HTML
replaces cache] H --> D style B fill:#27ae60,color:#fff style F fill:#e67e22,color:#fff style G fill:#4a90d9,color:#fff style H fill:#27ae60,color:#fff

Basic ISR Implementation

// pages/posts/[slug].js — ISR with time-based revalidation
export default function Post({ post, generatedAt }) {
    return (
        <article>
            <h1>{post.title}</h1>
            <p className="meta">
                Last generated: {new Date(generatedAt).toLocaleString()}
            </p>
            <div>{post.content}</div>
        </article>
    );
}

export async function getStaticPaths() {
    const res = await fetch('https://api.example.com/posts');
    const posts = await res.json();

    return {
        paths: posts.map(post => ({
            params: { slug: post.slug }
        })),
        fallback: 'blocking'
    };
}

export async function getStaticProps({ params }) {
    const res = await fetch(`https://api.example.com/posts/${params.slug}`);
    const post = await res.json();

    return {
        props: {
            post,
            generatedAt: Date.now()
        },
        // Revalidate every 60 seconds
        revalidate: 60
    };
}

How Stale-While-Revalidate Works

// ISR lifecycle visualization
const isrLifecycle = {
    step1: 'Build: Page is pre-rendered as static HTML',
    step2: 'Cache: Static file stored on CDN',
    step3: 'Request: User visits the page',
    step4: 'Check: Has revalidate window passed?',
    step5: 'No: Serve cached page directly (instant)',
    step6: 'Yes: Serve stale page immediately + trigger re-render',
    step7: 'Render: Server generates fresh HTML in background',
    step8: 'Update: New HTML replaces cache for next visitor'
};

// Visual representation
const staleTime = {
    served: 'Stale page (maybe seconds or minutes old)',
    reason: 'User gets instant response, no waiting',
    background: 'Fresh page being generated silently',
    nextUser: 'Gets the brand new page'
};

ISR with External Data

// pages/products/[id].js — E-commerce ISR
export async function getStaticProps({ params }) {
    const { id } = params;

    // Fetch product data
    const productRes = await fetch(`https://api.example.com/products/${id}`);

    if (!productRes.ok) {
        return { notFound: true };
    }

    const product = await productRes.json();

    // Also fetch inventory
    const inventoryRes = await fetch(
        `https://api.example.com/inventory/${id}`
    );
    const inventory = await inventoryRes.json();

    return {
        props: {
            product: {
                ...product,
                inStock: inventory.quantity > 0,
                stockCount: inventory.quantity
            },
            generatedAt: Date.now()
        },
        // Dynamic revalidate based on stock status
        revalidate: product.inStock ? 60 : 300
    };
}

Common Mistakes

  1. Setting revalidate too low. Revalidate: 1 means every Visitor triggers a re-render. Use 60+ seconds for most content or use on-demand revalidation.
  2. Not using fallback: 'blocking'. Without fallback, uncached pages return 404. 'blocking' generates them on first request and caches the result.
  3. Confusing revalidate with cache headers. revalidate controls ISR. Cache-Control headers control CDN Caching. Both are needed for correct behavior.
  4. Assuming ISR works without a server. ISR requires a persistent server runtime. Static export (output: 'export') doesn't support ISR.
  5. Not handling revalidation errors. If the re-render fails, stale content persists indefinitely. Monitor revalidation health.

Practice Questions

  1. What problem does ISR solve that SSG doesn't address?
  2. How does the stale-while-revalidate pattern work?
  3. What does the revalidate property control in getStaticProps?
  4. What happens during the background revalidation step?
  5. Why does ISR require a server runtime?

Challenge: Build a product catalog with ISR: implement time-based revalidation (120s), display the generation timestamp on each page, verify that stale content serves instantly while fresh content generates in the background, and measure the timing difference.

FAQ

Does ISR still serve static HTML files?

Yes. ISR serves cached static HTML. The re-rendered page is also saved as a static file. Users always get pre-built HTML, never a dynamic render.

What happens if the revalidate time hasn't passed?

The cached page serves immediately. No re-render is triggered. The page stays static until the revalidate window expires.

Can ISR update the entire site without a rebuild?

No. ISR only regenerates individual pages that are requested after their revalidate window expires. Full rebuild is still needed for global changes.

How does ISR affect server costs?

ISR reduces server costs compared to SSR because pages are cached and only regenerate when stale. However, it still needs a server, unlike pure SSG.

Does ISR work with all CDNs?

ISR works natively on Vercel. For other CDNs, you need to configure stale-while-revalidate Cache-Control headers and a server to handle revalidation.

Mini Project

Create an ISR-powered news ticker: build a page that displays current headlines with revalidate: 30, verify that the page updates automatically, show the last-generated timestamp, and compare the response time of ISR vs SSR for the same content.

What's Next

You understand ISR basics. Now compare ISR vs SSG vs SSR to know exactly when each rendering Strategy is appropriate.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro