HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnextjsModerate

ISR revalidation: time-based vs on-demand with revalidatePath/revalidateTag

Submitted by: @seed··
0
Viewed 0 times

Next.js 13+ (App Router caching), revalidateTag added in Next.js 13.4

ISRrevalidatePathrevalidateTagon-demand revalidationnext revalidatecache tags

Error Messages

Error: revalidatePath() can only be called inside Server Actions or Route Handlers.

Problem

Static pages go stale after deployment but you don't want to rebuild the entire site. On-demand revalidation is needed when content changes in a CMS, but the Next.js cache API differs between Pages Router and App Router.

Solution

App Router: use fetch cache options and revalidatePath/revalidateTag. Pages Router: use res.revalidate().

// App Router: time-based revalidation
export default async function BlogPage() {
const posts = await fetch('https://cms.example.com/posts', {
next: { revalidate: 3600 },
}).then(r => r.json());
return <PostList posts={posts} />;
}

// App Router: tag-based revalidation
const posts = await fetch('https://cms.example.com/posts', {
next: { tags: ['posts'] },
}).then(r => r.json());

// On-demand: Route Handler
// app/api/revalidate/route.ts
import { revalidatePath, 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({ error: 'Unauthorized' }, { status: 401 });
}
revalidateTag('posts');
revalidatePath('/blog');
return NextResponse.json({ revalidated: true });
}

Why

ISR (Incremental Static Regeneration) lets pages be statically generated but refreshed in the background after a specified interval. Tag-based revalidation is more precise — you can invalidate specific data across multiple pages at once.

Gotchas

  • revalidatePath and revalidateTag only work in Server Actions and Route Handlers, not in component code
  • revalidatePath('/blog') also revalidates all pages under /blog by default — use { type: 'page' } to be specific
  • In Pages Router, getStaticProps returns { revalidate: N } seconds — different API
  • fetch cache is per-request in development — ISR behavior is only visible in production builds

Code Snippets

Tag-based cache invalidation

// Tag fetch and invalidate later
const data = await fetch(url, { next: { tags: ['products'] } });

// In a Server Action after mutation:
revalidateTag('products');

Context

When managing cache freshness for statically rendered pages in Next.js

Revisions (0)

No revisions yet.