Next.js has three cache helpers with overlapping names: use cache, React cache(), and unstable_cache. They differ in two ways that matter most: how long an entry lasts and whether a new deploy resets it.
| Helper | Kind | Lifetime | Persists across deploys |
|---|---|---|---|
| use cache | Next.js directive | cacheLife profile | No |
| React cache() | React function | One server request | No |
| unstable_cache | Next.js function | revalidate seconds | Yes |
use cache
The use cache directive is the Cache Components way to cache. It keeps a result across requests for as long as its cacheLife profile allows, and it is how cached output joins the static shell during prerendering.
// app/lib/posts.ts
import { cacheLife } from 'next/cache'
export async function getPosts() {
'use cache'
cacheLife('hours')
const res = await fetch('https://api.example.com/posts')
return res.json()
}The entry is keyed partly by the build ID, so a fresh deploy starts with an empty cache. It runs on the server only and cannot read cookies or headers directly. See the use cache directive for its three placements.
React cache()
React cache() deduplicates calls within a single server request. It works in Server Components only, has no lifetime and no storage, so two components that call the same function with the same arguments run it once per request.
// app/lib/weather.ts
import { cache } from 'react'
export const getTemperature = cache(async (city: string) => {
const res = await fetch(`https://api.example.com/weather/${city}`)
return res.json()
})This is the right tool for ORM and database calls, which automatic fetch memoization cannot see. It must be defined at module scope, not inside a component, or every render creates a fresh memoized function. Unlike the framework cache, it holds nothing after the request finishes.
unstable_cache
unstable_cache wraps an async function for the pre-Cache-Components model. Unlike use cache, its entries persist across requests and deployments.
// app/lib/posts.ts
import { unstable_cache } from 'next/cache'
export const getCachedPosts = unstable_cache(
async () => {
const res = await fetch('https://api.example.com/posts')
return res.json()
},
['posts'],
{ tags: ['posts'], revalidate: 3600 }
)Next.js 16 recommends replacing it with use cache, and the function was never promoted past its unstable prefix. It remains the one to reach for when data must survive a deploy.
Which one to use
- Use
use cachefor any new caching in a Cache Components app. - Use React
cache()when you only need to deduplicate within one request. - Reach for
unstable_cacheonly when data must persist across deploys.
For moving existing unstable_cache calls over, see migrating from unstable_cache. Mixing the three in one file is fine, but name the one you mean, because their lifetimes do not line up.
Common mistakes
- Confusing React cache() with use cache. React cache() never persists, so wrapping it around a function does not cache across requests.
- Defining React cache() inside a component, which creates a new memoized function on every render.
- Reaching for unstable_cache in a Cache Components app, where use cache is the intended tool.
Rune AI
Key Insights
- use cache caches across requests within a deploy.
- React cache() deduplicates within one server request.
- unstable_cache persists across deploys, and use cache replaces it.
- Only use cache and cacheLife work inside Cache Components.
- Choose by lifetime and whether a deploy must reset the cache.
Frequently Asked Questions
Does React cache() persist across requests?
Which one survives a new deploy?
Conclusion
use cache is the current caching tool, React cache() deduplicates within one request, and unstable_cache persists across deploys, though Next.js 16 replaces it with use cache. Pick the narrowest one that fits the lifetime you actually need.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.