The use cache Directive: Next.js 16's New Approach to Caching
Next.js 16 introduces Cache Components — a new model where caching is declared inside functions with a directive, not set on routes or fetch calls. Here's how it works and when to adopt it.
May 25, 2026 · 5 min read
Last week we covered how to cache AI API responses using fetch options and unstable_cache. That model still works, but Next.js 16 ships a newer approach called Cache Components — and it changes where you express caching intent. Instead of annotating fetch calls or exporting route segment configs, you add a 'use cache' directive directly inside the function or component that produces the data.
The result is that caching lives next to the code being cached. That is easier to audit than a route-level export const revalidate = 60 that silently applies to everything in the file.
Enabling Cache Components
The feature is behind a flag in Next.js 16. Add cacheComponents: true to your next.config.ts:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
cacheComponents: true,
};
export default nextConfig;Once enabled, the old route segment configs (dynamic, revalidate, fetchCache) are replaced by use cache and cacheLife. The old fetch-based caching still works — the flag does not break existing behavior — but the new model is the intended path forward.
How use cache works
Add the directive at the top of any async function or component to cache its return value. You can place it at the file level (caches every export), component level, or function level:
// Function level — most surgical
export async function getProductSummary(slug: string) {
"use cache";
const res = await fetch(`https://api.example.com/products/${slug}`);
return res.json();
}
// Component level
export async function ProductCard({ slug }: { slug: string }) {
"use cache";
const data = await getProductSummary(slug);
return <div>{data.name}</div>;
}The cache key is derived automatically from the function's identity (a stable hash of its location in the codebase) plus its arguments. Pass different slugs, get separate cache entries — no manual key construction required.
Variables captured from outer scopes are also included in the key. If a cached function closes over auserId, different user IDs produce different entries without any extra work on your part.
Setting cache lifetimes with cacheLife
Inside a use cache scope, call cacheLife to declare how long the output should be considered fresh. Next.js ships named profiles that cover the most common cases:
import { cacheLife } from "next/cache";
export async function getAISummary(articleSlug: string) {
"use cache";
cacheLife("days"); // revalidate once per day
const { text } = await generateText({
model: openai("gpt-4o-mini"),
prompt: `Summarize: ${articleSlug}`,
});
return text;
}
export async function getLiveScore(matchId: string) {
"use cache";
cacheLife("seconds"); // near-real-time
return fetchScore(matchId);
}The profiles are: seconds (real-time data), minutes (social feeds), hours (inventory), days (blog posts), weeks (newsletters), and max (static legal pages). You can also pass a custom object with stale, revalidate, and expire values in seconds when the presets do not fit.
On-demand invalidation still uses revalidateTag
The tag-based invalidation API from the old model carries over. Use cacheTag inside a use cache scope to associate the entry with a tag, then call revalidateTag from a Server Action or Route Handler to purge it:
import { cacheLife, cacheTag } from "next/cache";
export async function getPost(slug: string) {
"use cache";
cacheLife("weeks");
cacheTag(`post-${slug}`, "posts");
return fetchPost(slug);
}
// In a Server Action triggered by a CMS webhook:
import { revalidateTag } from "next/cache";
revalidateTag("posts"); // invalidates all tagged entriesWhat this means for AI-native apps
The old model required you to wrap non-fetch AI SDK calls in unstable_cache and manually construct cache keys. With use cache, you add one directive and the framework handles key generation from your function signature and arguments. For AI apps where caching a fixed prompt response is the common case, this removes a meaningful amount of boilerplate.
The private variant — 'use cache: private' — lets you cache per-user data without routing it through a shared cache. That is the right tool when you need to persist a personalized AI response across a session without exposing it to other users, and without the complexity of a separate session store.
The short version: if you are on Next.js 16 and building anything AI-adjacent, turn on cacheComponents and start moving your caching intent into the functions that produce the data. The resulting code is easier to reason about and harder to get wrong.