Caching at the component level
Next.js 16 introduces 'use cache' as a primitive that works on entire components and functions, not just fetch(). It replaces experimental unstable_cache with a cleaner directive-based API.
Three building blocks
| API | Use |
|---|---|
'use cache' | Mark a component or function as cacheable |
cacheLife(profile) | Set the cache duration (built-in profiles or custom) |
cacheTag(...tags) | Tag the cached output for on-demand invalidation |
Built-in cacheLife profiles
Use a profile name and the framework picks reasonable defaults: 'seconds', 'minutes', 'hours', 'days', 'weeks', 'max'. Custom profiles can set stale / revalidate / expire independently.
How it composes with PPR
'use cache' integrates with Partial Prerendering: cached components render at build time and become part of the static shell, while uncached parts stay dynamic in the same route.
Before applying 'use cache', list every value that can change the result. Session identity, current time, and hidden module state must either be represented or excluded. Pair cacheLife with the tolerated age and cacheTag with the mutation that changes the result. After choosing a cache unit, prove reuse for equal inputs and separation for different inputs in logs. A tag that is too broad discards too much work, while one that is too narrow leaves stale results behind. Component caching does not make fetch caching obsolete. Cache the external response when several consumers share it; cache a function or rendered unit when the whole computation is the stable reusable boundary. Count executions of a slow database function across requests, test named and custom lifetimes, and update a narrow tag. Verify neighboring cached regions survive and that two users cannot receive a shared personalized result.