`cacheLife` Explained: Profiles, `stale`, `revalidate`, and `expire`

The cacheLife function sets how long a cached function or component stays fresh, using the stale, revalidate, and expire timings.

8 min read

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.

typescripttypescript
// 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

  • stale is how long the client shows cached content without checking the server. The default is 5 minutes.
  • revalidate is how often the server regenerates content in the background. The default is 15 minutes.
  • expire is 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:

Profilestalerevalidateexpire
default5 minutes15 minutesnever
seconds30 seconds1 second1 minute
minutes5 minutes1 minute1 hour
hours5 minutes1 hour1 day
days5 minutes1 day1 week
weeks5 minutes1 week30 days
max5 minutes30 days1 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:

typescripttypescript
// next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  cacheComponents: true,
  cacheLife: {
    editorial: {
      stale: 600,
      revalidate: 3600,
      expire: 86400,
    },
  },
}
 
export default nextConfig

Any 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:

typescripttypescript
// 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

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.
RunePowered by Rune AI

Frequently Asked Questions

Can cacheLife be called outside a use cache scope?

No. cacheLife only works inside a cached function or component. Calling it at module scope throws an error.

What happens if I omit cacheLife?

The default profile applies, with a 5 minute stale time, a 15 minute revalidate time, and no expiry.

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.