How Next.js Cache Revalidation Works: Time-Based, On-Demand, Stale Data, and Expiry

Revalidation updates cached data without dropping the cache. Learn time-based and on-demand revalidation, and what stale, revalidate, and expire mean.

8 min read

In Next.js, cache revalidation is how cached data gets updated without dropping the cache. Under Cache Components there are two strategies: time-based revalidation with cacheLife, and on-demand revalidation with revalidateTag, updateTag, and revalidatePath. Most apps combine both.

Cache lookup and revalidation flow

A request first checks the cache. A fresh entry is served immediately, a stale entry is served while fresh data loads in the background, and an expired entry blocks until fresh data is ready.

Time-based revalidation

cacheLife sets a lifetime on a cached scope, and the framework refreshes the entry when that time passes. The lifetime has three timings.

  • stale is how long the client trusts cached data without checking the server.
  • revalidate is how often the server regenerates data in the background.
  • expire is the maximum age before the next request must block for fresh data.

You pick a profile name or pass an object with the three values. For the full profile list, see cacheLife explained.

On-demand revalidation

When a mutation happens, invalidate the affected entries by tag or by path. Tag data with cacheTag, then expire it after the write.

typescripttypescript
// app/actions.ts
'use server'
 
import { updateTag } from 'next/cache'
 
export async function publishPost(id: string) {
  await db.posts.publish(id)
  updateTag(`post-${id}`)
  updateTag('posts')
}

This expires both the single post and the list, so the next request for either waits for fresh data. updateTag runs in Server Actions only, while revalidateTag works in Route Handlers too and refreshes in the background, serving stale content while it rebuilds. See revalidateTag vs updateTag for the choice.

Which strategy to use

Use time-based revalidation when content changes on a predictable schedule, such as an inventory feed that updates hourly. Use on-demand revalidation when content changes only when someone edits it, such as a blog post, and pair a long cacheLife with a tag so the page stays in the static shell between edits.

What to cache

Cache data that does not depend on the request and that you are comfortable serving for a set period. For CMS content that changes rarely, tag it and revalidate from a webhook instead of a timer, so unchanged content is not rebuilt for no reason.

In serverless environments, remember that in-memory entries may not survive between revalidations. Time-based and on-demand strategies are not exclusive, and a blog that tags its posts and also refreshes hourly combines both.

The practical rule is to tag entries where they are cached and invalidate them where the mutation happens, so the two halves stay close to the code that owns them.

Rune AI

Rune AI

Key Insights

  • Time-based revalidation uses cacheLife profiles.
  • On-demand revalidation uses revalidateTag, updateTag, or revalidatePath.
  • stale controls the client, revalidate the server refresh, expire the hard limit.
  • updateTag expires immediately, revalidateTag refreshes in the background.
  • Use tags for shared data and paths for a single route.
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between stale and expire?

stale is how long the client trusts cached data without checking. expire is the maximum age before the next request must block and rebuild.

Is revalidation automatic or manual?

Both. Time-based revalidation happens on a timer through cacheLife, and on-demand revalidation happens after a mutation through revalidateTag, updateTag, or revalidatePath.

Conclusion

Revalidation is the bridge between speed and freshness. cacheLife revalidates on a timer, and tags or paths revalidate after an event. stale, revalidate, and expire each control a different stage of that life.