Revalidating

Learn how to revalidate cached data using time-based and on-demand strategies.

This page covers revalidation with Cache Components, enabled by setting cacheComponents: true in your next.config.ts file. If you're not using Cache Components, see the Caching and Revalidating (Previous Model) guide.

Revalidation is the process of updating cached data. It lets you keep serving fast, cached responses while ensuring content stays fresh. There are two strategies:

cacheLife

cacheLife controls how long cached data remains valid. Use it inside a use cache scope to set the cache lifetime.

app/lib/data.ts
import { cacheLife } from 'next/cache'
 
export async function getProducts() {
  'use cache'
  cacheLife('hours')
  return db.query('SELECT * FROM products')
}

cacheLife accepts a profile name or a custom configuration object:

Profilestalerevalidateexpire
seconds01s60s
minutes5m1m1h
hours5m1h1d
days5m1d1w
weeks5m1w30d
max5m30d~indefinite

For fine-grained control, pass an object:

'use cache'
cacheLife({
  stale: 3600, // 1 hour until considered stale
  revalidate: 7200, // 2 hours until revalidated
  expire: 86400, // 1 day until expired
})

Good to know: A cache is considered "short-lived" when it uses the seconds profile, revalidate: 0, or expire under 5 minutes. Short-lived caches are automatically excluded from prerenders and become dynamic holes instead. See Prerendering behavior for details.

See the cacheLife API reference for all profiles and custom configuration options.

cacheTag

cacheTag lets you tag cached data so it can be invalidated on-demand. Use it inside a use cache scope:

import { cacheTag } from 'next/cache'
 
export async function getProducts() {
  'use cache'
  cacheTag('products')
  return db.query('SELECT * FROM products')
}

Once tagged, invalidate the cache using revalidateTag or updateTag.

See the cacheTag API reference to learn more.

revalidateTag

revalidateTag invalidates cache entries by tag using stale-while-revalidate semantics — stale content is served immediately while fresh content loads in the background. This is ideal for content where a slight delay in updates is acceptable, like blog posts or product catalogs.

import { revalidateTag } from 'next/cache'
 
export async function updateUser(id: string) {
  // Mutate data
  revalidateTag('user', 'max') // Recommended: stale-while-revalidate
}

You can reuse the same tag in multiple functions to revalidate them all at once. Call revalidateTag in a Server Action or Route Handler.

Good to know: The second argument sets how long stale content can be served while fresh content generates in the background. Once it expires, subsequent requests block until fresh content is ready. Using 'max' gives the longest stale window.

See the revalidateTag API reference to learn more.

updateTag

updateTag immediately expires cached data for read-your-own-writes scenarios — the user sees their change right away instead of stale content. Unlike revalidateTag, it can only be used in Server Actions.

import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
 
export async function createPost(formData: FormData) {
  const post = await db.post.create({
    data: {
      title: formData.get('title'),
      content: formData.get('content'),
    },
  })
 
  updateTag('posts')
  redirect(`/posts/${post.id}`)
}
updateTagrevalidateTag
WhereServer Actions onlyServer Actions and Route Handlers
BehaviorImmediately expires cacheStale-while-revalidate
Use caseRead-your-own-writes (user sees their change)Background refresh (slight delay OK)

See the updateTag API reference to learn more.

revalidatePath

revalidatePath invalidates all cached data for a specific route path. Use it when you want to revalidate a route without knowing which tags are associated with it.

import { revalidatePath } from 'next/cache'
 
export async function updateUser(id: string) {
  // Mutate data
  revalidatePath('/profile')
}

Good to know: Prefer tag-based revalidation (revalidateTag/updateTag) over path-based when possible — it's more precise and avoids over-invalidating.

See the revalidatePath API reference to learn more.

What should I cache?

Cache data that doesn't depend on runtime data and that you're OK serving from cache for a period of time. Use use cache with cacheLife to describe that behavior.

For content management systems with update mechanisms, use tags with longer cache durations and rely on revalidateTag to refresh content when it actually changes, rather than expiring the cache preemptively.

On this page