Revalidation
Cached data is refreshed either by time (cacheLife) or on demand after a mutation. For on-demand revalidation there are three functions:
updateTag | revalidateTag | revalidatePath | |
|---|---|---|---|
| Target | Entries with a tag | Entries with a tag | Everything on a route |
| Behavior | Expires immediately | Stale-while-revalidate | Invalidates the path |
| Where | Server Actions only | Server Actions, Route Handlers | Server Actions, Route Handlers |
| Use case | User must see their own change | Background refresh, a small delay is fine | No tags known for the route |
Example
ts
'use server';
import { updateTag } from 'next/cache';
export async function addComment(postId: string, text: string) {
await db.comment.create({ data: { postId, text } });
updateTag(`post-${postId}`); // the author sees the comment right away
}ts
// app/api/cms-webhook/route.ts
import { revalidateTag } from 'next/cache';
export async function POST() {
revalidateTag('posts', 'max'); // serve stale content while fresh content is generated
return Response.json({ ok: true });
}Tips
- Prefer tags over paths: they are precise and don't invalidate unrelated data.
- For content from a CMS use a long
cacheLife('max')+cacheTagand callrevalidateTagfrom a webhook instead of polling by time. router.refresh()only refetches the current route on the client, it does not clear the server cache.
updated
did you know it?