revalidateTag and updateTag both invalidate a cache tag, but they answer different questions. updateTag expires data immediately so the person who made the change sees it right away, while revalidateTag serves stale data and refreshes in the background. Both run on the server.
| updateTag | revalidateTag | |
|---|---|---|
| Where | Server Actions only | Server Actions and Route Handlers |
| Behavior | Immediately expires the tag | Stale-while-revalidate |
| Use case | Read-your-own-writes | Background refresh is fine |
When to use updateTag
After a form submission, the user should see their own change without a stale flash. updateTag expires the tag so the next request waits for fresh data.
// app/actions.ts
'use server'
import { updateTag } from 'next/cache'
export async function createPost(title: string) {
await db.posts.create({ title })
updateTag('posts')
}The next visitor who reads anything tagged posts gets fresh data, and the submitting user sees the new post immediately. Because it expires the tag, every page that reads posts re-fetches on its next request. updateTag can only run inside a Server Action, which is exactly the read-your-writes case it exists for.
When to use revalidateTag
For content where a short delay is fine, revalidateTag marks the tag stale and lets the client keep using cached data while fresh data loads.
// app/api/webhook/route.ts
import { revalidateTag } from 'next/cache'
export async function POST() {
revalidateTag('posts', 'max')
return Response.json({ ok: true })
}The second argument is a cache profile, and max is the recommended value because it gives stale-while-revalidate behavior: the cached copy keeps serving while the refresh runs. Without it, the single-argument form is deprecated and raises a TypeScript error. To expire immediately from a webhook, pass an object instead, such as revalidateTag('posts', { expire: 0 }), which makes the next request block for fresh data rather than serving stale content.
A revalidation endpoint like this is publicly reachable, so verify a shared secret from the request before invalidating anything.
Which one to call
Pick updateTag when the mutation happens in a Server Action and the user must see the result now. Pick revalidateTag in Route Handlers, webhooks, or when a background refresh is good enough. A tag with no matching entries is a no-op, so the name must match the one you assigned when caching.
Tags only work if something assigned them first, either cacheTag inside a cached function or next.tags on a fetch request. See cacheTag explained for how tagging works, and revalidatePath explained for invalidating by route instead of by tag.
Common mistakes
- Calling updateTag from a Route Handler or webhook, which throws because it is Server Actions only.
- Calling revalidateTag with only a tag, which is the deprecated single-argument form.
- Invalidating a tag that was never assigned, so nothing happens.
Rune AI
Key Insights
- updateTag is Server Actions only and expires data immediately.
- revalidateTag works in actions and route handlers with stale-while-revalidate.
- revalidateTag needs a cacheLife profile as its second argument.
- Tags must be assigned with cacheTag or next.tags first.
- Pass { expire: 0 } for immediate webhook expiration.
Frequently Asked Questions
Where can updateTag be called?
Does revalidateTag still work with one argument?
Conclusion
Use updateTag in Server Actions when the user must see their own change immediately, and revalidateTag everywhere else when serving stale data during a background refresh is acceptable. Both require the tag to be assigned with cacheTag or next.tags first.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.