The Limitations of Time-Based ISR

Incremental Static Regeneration (ISR) has long been one of Next.js’\”s most compelling capabilities, allowing developers to generate static pages at build time while updating them in the background without full site redeployments. However, naive time-based revalidation (revalidate: 60) suffers from inherent trade-offs: either pages serve stale data for up to 60 seconds, or high-traffic origin servers get hammered with constant regeneration requests.

In Next.js 15, On-Demand Tag-Based Revalidation (revalidateTag) provides millisecond-level cache invalidation across distributed edge nodes the instant CMS or database content updates.

Published by Saizul Amin for frontend engineering leaders and enterprise web developers.

Time-Based Revalidation vs. On-Demand Tag Invalidation

Dimension Time-Based ISR (e.g. 60s) On-Demand Tag Invalidation (revalidateTag)
Data Freshness Stale up to TTL window; unpredictable Instantaneous (0s delay upon mutation)
Origin Server Load Continuous background builds every 60s per URL Zero builds until actual content changes
Cache Hit Ratio Drops every 60 seconds across all regions > 99.2% sustained CDN edge hit rate
Purge Granularity Broad time-bucketed invalidation Granular entity tags (e.g. collection:shoes)

Code Architecture: Tagged Fetch in Next.js 15 App Router


// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
  // Fetch with multiple granular cache tags
  const res = await fetch(`https://api.saizul.com/products/${params.id}`, {
    next: {
      tags: [`product:${params.id}`, '\''products'\'', '\''inventory'\''],
    },
  });

  const product = await res.json();

  return (
    <div className="max-w-4xl mx-auto py-12">
      <h1 className="text-3xl font-bold">{product.name}</h1>
      <p className="text-emerald-500 font-semibold">${product.price}</p>
      <div className="mt-4">Stock Status: {product.inStock ? '\''In Stock'\'' : '\''Sold Out'\''}</div>
    </div>
  );
}

Triggering Instant Webhook Revalidation via Route Handler


// app/api/revalidate/route.ts
import { NextRequest, NextResponse } from '\''next/server'\'';
import { revalidateTag } from '\''next/cache'\'';

export async function POST(request: NextRequest) {
  const secret = request.headers.get('\''x-revalidation-secret'\'');
  if (secret !== process.env.REVALIDATION_SECRET) {
    return NextResponse.json({ message: '\''Invalid token'\'' }, { status: 401 });
  }

  const { tag } = await request.json();
  if (!tag) {
    return NextResponse.json({ message: '\''Missing tag'\'' }, { status: 400 });
  }

  // Instantly purges cache across all edge locations
  revalidateTag(tag);

  return NextResponse.json({ revalidated: true, tag, now: Date.now() });
}

NEW BLOGS. REAL STRATEGIES. REAL RESULTS.

Join our community and receive powerful SEO tips, web optimization guides, and growth strategies as soon as they’re published.

Don’t just read blogs — stay ahead of the competition.

We don’t spam! Read our privacy policy for more info.

Share.
Leave A Reply