Caching is the single most consequential and most misunderstood part of the App Router, because it is the mechanism that makes Next.js fast but also the mechanism that, when misunderstood, makes data appear stale or refuse to update. The framework does not have one cache; it has a layered system of several distinct caches, each operating at a different stage of the request lifecycle and each with its own rules for what it stores, how long it holds it, and what invalidates it. There is a Request Memoization layer that deduplicates identical fetches within a single render, a Data Cache that persists fetch results across requests and deployments, a Full Route Cache that stores the rendered HTML and RSC payload of static routes at build time, and a Router Cache that holds visited routes in the browser for instant back-and-forward navigation. Understanding caching means understanding which of these layers a given piece of data passes through and what controls each one.
This layered design exists because the alternatives are both bad: caching nothing means every request re-does expensive work and the app is slow, while caching everything with no controls means users see outdated information and lose trust. By separating caching into independent layers with explicit controls, the App Router lets you make a deliberate, per-resource decision about freshness versus speed rather than accepting one global tradeoff. The cost of this power is that you must actually learn the layers, because the defaults are aggressive and a developer who does not know that fetch results are cached by default will be baffled when their dashboard shows yesterday's numbers. The rest of this lesson maps each layer, the options that control it, and the revalidation strategies — time-based and on-demand — that keep cached data correct without sacrificing the speed the caches provide.