Tag, then invalidate
updateTag for your own write, revalidateTag in the background.
From next-cache-components, “Cache Invalidation”.
Save, then refresh
Change the price, save, then refresh each side.
Database: $20
revalidateTagBad here$20HIT
stale after saveupdateTagGood$20HIT
fresh after save// lib/products.ts
import { cacheTag } from 'next/cache'
export async function getProduct(id: string) {
'use cache'
cacheTag('products', `product-${id}`)
return db.products.findUnique({ where: { id } })
}
// app/products/[id]/actions.ts
'use server'
import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export async function updateProduct(id: string, data: FormData) {
await db.products.update({ where: { id }, data })
updateTag(`product-${id}`)
redirect(`/products/${id}`)
}
Blast radius of one edit
Hover to preview; tap or click to add $5.
One broad tagBad
updateTag('products')Broad + per-item tagsGood
updateTag(`product-${id}`)async function getProducts() {
'use cache'
const items = await db.products.findMany()
// The list shows every item, so it carries every item's tag too.
cacheTag('products', ...items.map((p) => `product-${p.id}`))
return items
}
async function getProduct(id: string) {
'use cache'
cacheTag('products', `product-${id}`)
return db.products.findUnique({ where: { id } })
}
Type the invalidation call
Type a call or pick an example.
'use server'
import { revalidateTag, updateTag } from 'next/cache'
export async function createPost(data: FormData) {
await db.posts.create({ data })
revalidateTag('posts', 'max')
}
export async function updateProduct(id: string, data: FormData) {
await db.products.update({ where: { id }, data })
updateTag(`product-${id}`)
}
Why it matters, pros and cons
Why it matters
A tag names data, not routes, so one write reaches every cache that read it.
Pros
- Per-item tags evict one entry
updateTagshows your own writerevalidateTagnever blocks a request
Cons
updateTagonly works inside a Server Action- Lists go stale unless they carry item tags
- A missed tag fails silently