Caching Then and Now

What Next.js Caches, Then and Now

If you learned the App Router before 2025, you learned a diagram with four boxes: request memoization, the Data Cache, the Full Route Cache and the client Router Cache, sitting behind a fetch that cached everything it could unless you passed cache: 'no-store'. That model went in two steps. Next.js 15 10,514 flipped the fetch default, so requests are no longer cached unless you ask. Next.js 16 made the whole render dynamic by default and introduced Cache Components as the single way back in. The segment exports that used to steer the old caches — dynamic, dynamicParams, revalidate and fetchCache — are removed when Cache Components is enabled, and experimental.ppr and experimental.dynamicIO were deleted outright.

The old implicit caches and what replaces them
Concern Next.js 13-14 Next.js 16.3 with Cache Components
fetch in a Server Component cached by default never cached by default
Cross-request data cache Data Cache, implicit use cache on a function
Cached page output Full Route Cache, implicit use cache on a page or layout
Lifetime revalidate export, next.revalidate cacheLife profile
Invalidation revalidateTag, revalidatePath updateTag, revalidateTag, refresh
Mixing static and dynamic experimental.ppr on by default

One piece of the old diagram survives unchanged: React 7,897 still deduplicates identical fetch calls inside a single render pass, so two components asking for the same URL make one request. That is request memoization, not a cache across requests, and Parallel Requests covers it.

Migration is mostly subtraction. Delete export const revalidate, drop cache: 'force-cache' and next: { revalidate } from your fetch calls, then add "use cache" and a cacheLife to the functions whose results you actually want shared. If you are not ready, the previous model still works: leave cacheComponents off and keep unstable_cache and the segment exports. The two are alternatives, not layers.