Revalidation and Cache Components: revalidatePath, revalidateTag and "use cache"

Intermediate
13 min

Revalidation and Cache Components: revalidatePath, revalidateTag and "use cache"

Caching makes Next.js fast, but a cache you cannot clear is a bug factory: an editor publishes a post and the site keeps showing the old list. This lesson covers the tools that keep cached data correct. After it you will be able to expire cached data on a timer or on demand with revalidatePath and revalidateTag, and cache any async function with the "use cache" directive.

The Caches Next.js Manages

| Cache | Lives | Stores | Cleared by | |---|---|---|---| | Request memoization | One render pass | Identical fetch calls | Automatically after the render | | Data Cache | Server, across requests | fetch results and "use cache" output | revalidatePath, revalidateTag, time | | Full Route Cache | Server, across requests | Static HTML and RSC payload | Same as Data Cache | | Router Cache | Browser | Visited route payloads | router.refresh(), navigation, actions |

Time-based expiry (revalidate) was covered earlier; here we focus on on-demand revalidation and the newer caching model.

revalidatePath: Purge a Route

revalidatePath marks a route's cached data and HTML as stale. The next visit regenerates it. It is typically called from a Server Action or a Route Handler after a write:

typescript
// app/actions.ts "use server"; import { revalidatePath } from "next/cache"; import { db } from "@/lib/db"; export async function addComment(postId: string, text: string) { await db.comment.create({ data: { postId, text } }); revalidatePath(`/posts/${postId}`); // this page only }

Pass "page" (the default) to target one route or "layout" to include every child route.

revalidateTag: Purge by Name

Paths are a blunt instrument when the same data appears in ten places. Tags let you name data and purge every consumer at once. Attach tags to fetch calls:

typescript
const res = await fetch("https://api.example.com/posts", { next: { tags: ["posts"] }, });

Then, wherever the data changes:

typescript
import { revalidateTag } from "next/cache"; revalidateTag("posts", "max");

The second argument, introduced in Next.js 16, is a cache-life profile that controls how the stale entry is served while fresh data loads in the background; "max" is the usual choice. Inside a Server Action, updateTag("posts") expires the entry immediately so the same request can read its own write.

Cache Components and the "use cache" Directive

fetch options only cover HTTP calls. Database queries, file reads and expensive computations need something else. Enable Cache Components in next.config.ts:

typescript
import type { NextConfig } from "next"; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig;

Now any async function, component or whole file can opt into caching with a directive, as shown in the sample at the top of this lesson. Two helpers refine it:

  • cacheLife("seconds" | "minutes" | "hours" | "days" | "weeks" | "max") sets how long the result is reused; a custom object with stale, revalidate and expire also works.
  • cacheTag("name") connects the entry to revalidateTag.

The directive replaces the older unstable_cache helper. With Cache Components enabled, Next.js also pre-renders a static shell for every route and streams only the parts that read request data, so any component that touches cookies(), headers() or uncached data must sit inside a <Suspense> boundary; the build reports an error if it does not.

Common mistakes

  • Calling revalidatePath during render instead of inside an action or handler; it only takes effect after a mutation.
  • Forgetting that "use cache" functions receive serializable arguments only; the arguments form the cache key.
  • Expecting revalidateTag to refresh the browser: the Router Cache updates after navigation, router.refresh() or a completed Server Action.
Quick Quiz
Question 1 of 3

Which call purges every cached `fetch` result tagged `"products"`?

Key Takeaways

  • Next.js keeps four caches; the Data Cache and Full Route Cache are the ones you revalidate.
  • revalidatePath purges a route (or a whole layout subtree); revalidateTag purges named data anywhere it is used.
  • Tag fetch calls with next: { tags } and cached functions with cacheTag().
  • "use cache" with cacheLife caches any async work once cacheComponents is enabled in next.config.ts.
  • With Cache Components on, dynamic data must live inside <Suspense> so a static shell can be pre-rendered.

Next lesson: Streaming and Suspense — send the fast parts of a page first and stream the slow parts as they resolve.

Revalidation and Cache Components: revalidatePath, revalidateTag and "use cache" - Next.js | CodeYourCraft | CodeYourCraft