cacheLife sets the lifetime of a cached function or component. It only works inside a use cache scope, so it assumes Cache Components is enabled, and it defines three timings: how long the client trusts the cache, how often the server refreshes it, and when it expires for good.
// 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 hours profile gives the whole cached result a lifetime, so the entry is reused for an hour before the server refreshes it in the background. This runs on the server only.
The three timings
staleis how long the client shows cached content without checking the server. The default is 5 minutes.revalidateis how often the server regenerates content in the background. The default is 15 minutes.expireis the maximum age before the next request waits for fresh content. The default is that it never expires.
Set revalidate shorter than expire. Next.js validates this and raises an error when the order is wrong.
Preset profiles
Next.js ships named profiles that combine the three values:
| Profile | stale | revalidate | expire |
|---|---|---|---|
| default | 5 minutes | 15 minutes | never |
| seconds | 30 seconds | 1 second | 1 minute |
| minutes | 5 minutes | 1 minute | 1 hour |
| hours | 5 minutes | 1 hour | 1 day |
| days | 5 minutes | 1 day | 1 week |
| weeks | 5 minutes | 1 week | 30 days |
| max | 5 minutes | 30 days | 1 year |
Use the profile name as a string, such as cacheLife('days'). If you omit the call, the default profile applies.
Custom profiles
Define your own profile in the config file, then reference it by name across the app:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
cacheLife: {
editorial: {
stale: 600,
revalidate: 3600,
expire: 86400,
},
},
}
export default nextConfigAny property you leave out inherits from the default profile. This sits in the same config file as the cacheComponents flag.
Inline profiles
For a one-off lifetime, pass an object directly instead of naming a profile:
// app/lib/limited-offer.ts
import { cacheLife } from 'next/cache'
export async function getLimitedOffer() {
'use cache'
cacheLife({ stale: 60, revalidate: 300, expire: 3600 })
const res = await fetch('https://api.example.com/limited-offer')
return res.json()
}This applies only to the function that calls it. Use named profiles for anything reused.
How short lifetimes change prerendering
A very short lifetime changes where content is served from. When revalidate is zero or expire is under 5 minutes, the entry is excluded from prerenders and becomes a dynamic hole resolved at request time. For the full explanation, see why a short cacheLife stops your page from prerendering.
Common mistakes
- Calling cacheLife at module scope instead of inside a cached function.
- Calling it more than once per invocation through different branches, when only one should run.
- Omitting the call and then being surprised that the default profile applies.
For where the directive itself can go, see the use cache directive.
Rune AI
Key Insights
- cacheLife only works inside a use cache scope.
- stale controls the client cache, revalidate the server refresh.
- expire is the hard limit before a synchronous rebuild.
- Preset profiles go from seconds to max.
- Omitted cacheLife falls back to the default profile.
Frequently Asked Questions
Can cacheLife be called outside a use cache scope?
What happens if I omit cacheLife?
Conclusion
cacheLife turns a vague cache into a stated lifetime. Set stale for the client, revalidate for the server, and expire as the hard limit, and prefer an explicit profile over the implicit default.
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.