Mutations & Revalidation

After Writing, Revalidate the Cache

Mutations & Revalidation

Every Server Action that changes data should pair the write with a `revalidatePath` or `revalidateTag` call so subsequent reads see the new state.

4 min read Level 2/5 #nextjs#mutations#revalidation
What you'll learn
  • Insert, update, and delete, then revalidate
  • Pick path vs tag based on scope of change
  • Avoid stale UIs caused by missing revalidation

The single most common bug with Server Actions is forgetting to revalidate. The write succeeds, but the page shows yesterday’s data until the cache TTL expires. The fix is mechanical: write, then revalidate.

Insert

'use server'
import { revalidatePath } from 'next/cache'

export async function createTodo(form: FormData) {
  await db.todos.insert({ text: String(form.get('text') ?? '') })
  revalidatePath('/todos')
}

Update

'use server'
export async function toggleTodo(id: string) {
  await db.todos.update(id, { done: true })
  revalidatePath('/todos')
}

Delete

'use server'
export async function deleteTodo(id: string) {
  await db.todos.delete(id)
  revalidatePath('/todos')
}

Path vs Tag

revalidatePath('/todos') invalidates one route. Use it when a single page shows the data. revalidateTag('todos') invalidates every fetch tagged 'todos' — use it when the same data is shown in multiple places (a sidebar count, a feed, a dashboard).

import { revalidateTag } from 'next/cache'
await db.todos.update(id, { done: true })
revalidateTag('todos')

When Both Make Sense

A blog post mutation might want both: revalidatePath('/blog/' + slug) for the detail page and revalidateTag('posts') for the index and the home-page feed.

Optimistic Updates →