Revalidating Data After a Server Action

How to refresh cached pages after a Server Action with revalidatePath, updateTag, and refresh, and when to use each.

7 min read

A Server Action that changes data does not refresh cached pages on its own. Revalidating data after a Server Action is the step that tells Next.js which cached pages or tags are now wrong.

You do that with revalidatePath for a path or updateTag for tagged data. Choosing the right call keeps a mutation from leaving stale pages behind. In Next.js 16 with Cache Components, data is dynamic by default, so you only revalidate what you deliberately cached.

Here is the basic flow. After the action writes the change, it calls revalidatePath for the page that shows the result.

index.tsindex.ts
// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
let posts = [{ id: 1, title: 'First post' }]
export async function renamePost(formData: FormData) {
  const id = Number(formData.get('id'))
  const title = formData.get('title')?.toString()
  posts = posts.map((p) => (p.id === id ? { ...p, title } : p))
  revalidatePath('/posts')
}

After this action runs, the cached data for /posts is invalid. Because the call happened inside a Server Action, Next.js also re-renders the current route on the server and sends that markup back in the same response, so the visitor sees the new title without a second request.

Other pages that were not re-rendered pick up the change the next time they are visited.

Revalidation inside a Server Action

The order matters. The action writes first, then invalidates the cache, and only then does Next.js re-render.

That single response carries both the action's return value and the fresh markup for the page the visitor is on. Pages you did not revalidate keep serving their cached copy until their own tag or path is invalidated.

Revalidate a path with revalidatePath

revalidatePath takes a path or a route pattern. Pass a literal path to refresh one page, or a pattern with a type to refresh every page matching it.

index.tsindex.ts
// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
 
export async function refreshBlog() {
  revalidatePath('/posts')
  revalidatePath('/blog/[slug]', 'page')
}

The first call refreshes the single page at /posts. The second refreshes every page rendered by app/blog/[slug]/page.tsx, which is useful after an edit that touches many posts at once.

Use a literal path when you know the exact URL, and a route pattern when you want every page produced by one file. A pattern does not reach deeper routes, so /blog/[slug] leaves /blog/[slug]/[author] alone.

For a dynamic segment you must pass the type, either page or layout. revalidatePath only runs in server environments, so it belongs inside the action, never in a Client Component. See revalidatePath explained for the full parameter rules.

Expire tagged data with updateTag

Tagged caching works differently from paths. You assign a tag when data is cached, then expire every entry carrying that tag after a mutation.

index.tsindex.ts
// app/actions.ts
'use server'
import { updateTag } from 'next/cache'
const drafts = new Set(['post-1'])
 
export async function publishPost(formData: FormData) {
  const id = formData.get('id')?.toString()
  if (id) drafts.delete(id)
  updateTag('posts')
  return { id }
}

The tag posts must have been applied where the data was cached, such as with cacheTag inside a use cache function or with the next.tags option on fetch. updateTag then expires every cache entry carrying that tag, and the next read waits for fresh data rather than serving the old copy.

That waiting is the point. It is what lets a user see their own write immediately instead of the version that was cached a moment earlier.

Tagged revalidation is broader than a path: one updateTag call can refresh a list page, a detail page, and a dashboard at once, as long as they cached data with the same tag.

updateTag works only inside a Server Action. In a Route Handler or a webhook, reach for revalidateTag instead. See revalidateTag vs updateTag to choose between them.

Refresh the client router

Sometimes a mutation changes state that was never cached in the first place, and the page just needs to be rendered again. The refresh function from next/cache refetches the current route without invalidating any cached data.

index.tsindex.ts
// app/actions.ts
'use server'
import { refresh } from 'next/cache'
 
let unread = 3
 
export async function markAllRead() {
  unread = 0
  refresh()
}

After this action, the current route re-renders on the server and the visitor sees an unread count of zero. Nothing in the cache was touched, because there was nothing cached to invalidate.

refresh only works inside a Server Action. Calling it from a Route Handler or a Client Component throws, and it is a different thing from the router.refresh() you call on the client.

It also does not revalidate tagged data. Pair it with updateTag when the same mutation changed cached data that other pages read.

Which call to use

NeedCall
Refresh one path or a route patternrevalidatePath
Expire tagged data across pagesupdateTag
Update the current route immediatelyrefresh

The three calls answer different questions: which page, which data, or what the user sees right now. Pick the one that matches the scope of your change.

They are not exclusive. A single action often calls revalidatePath for the page it just changed and updateTag for the tag that other pages share, so both the current view and the rest of the app stay consistent.

Call revalidation before redirect, because redirect stops execution and any code after it does not run. For the mutation that precedes these calls, see how to mutate data with a Server Action.

Rune AI

Rune AI

Key Insights

  • Server Actions do not invalidate caches on their own.
  • Use revalidatePath for a path or route pattern.
  • Use updateTag to expire every cache entry carrying a tag.
  • refresh updates the client router without touching tagged data.
  • Call revalidation before redirect, since redirect stops execution.
RunePowered by Rune AI

Frequently Asked Questions

Does a Server Action refresh pages automatically?

No. A mutation does not invalidate caches by itself. You must call revalidatePath or updateTag inside the action to tell Next.js which pages or tags need fresh data.

What is the difference between revalidateTag and updateTag?

updateTag expires tagged data immediately and is recommended in Server Actions. revalidateTag marks data stale with stale-while-revalidate behavior, and its single-argument form is deprecated.

Can I call revalidatePath in a Client Component?

No. revalidatePath only works in server environments, which means inside Server Functions or Route Handlers. It cannot be called in Client Components or Proxy.

Conclusion

After a Server Action mutates data, call revalidatePath to refresh a path, updateTag to expire tagged data, or refresh to update the client router. In Next.js 16 with Cache Components you only revalidate what you deliberately cached.