NextjsCaching Deep Dive

Caching Deep Dive

The App Router caches aggressively, by default, at four distinct layers — and each layer caches a different thing, for a different reason, invalidated by different triggers. Understanding which layer is responsible for a piece of stale data you're staring at is most of the battle when debugging "why isn't this updating?".

Note
This is consistently one of the most confusing aspects of the App Router for newcomers — not because any single mechanism is complicated on its own, but because all four operate at once, and the same page can be affected by two or three of them simultaneously.
The four mechanisms, at a glance

Mechanism

What is cached

Where

How long

Request Memoization

The return value of an identical fetch call (same URL + options)

Server, per-request only

Duration of a single render pass — cleared once the request finishes

Data Cache

The return value of fetch calls (or unstable_cache-wrapped functions) across requests

Server, persists across requests and deployments

Indefinite by default, or a revalidate interval you set — until explicitly revalidated

Full Route Cache

The rendered HTML + RSC payload for a statically-rendered route

Server (typically at the CDN/edge)

Indefinite for static routes — until a new deployment or revalidatePath/revalidateTag

Router Cache

RSC payloads for routes the user has visited or prefetched, on the client

Browser, per session

A short window (session-based); cleared on full page reload or after a Server Action's revalidatePath

Request Memoization
If the same fetch URL with the same options is called multiple times while rendering one page — say, both a layout and a page each call the same "get current user" function — React memoizes the result so only the first call actually hits the network. This is scoped to a single request only; it never persists between separate visitors or reloads.

Two components, one fetch, during a single render

TSX
// layout.tsx and page.tsx both call this during the same request.
// The second call reuses the first call's in-flight/completed result.
async function getUser() {
  const res = await fetch('https://api.example.com/me')
  return res.json()
}
Data Cache
The Data Cache persists fetch results across separate requests and even across deployments, on the server. By default a fetch call is cached indefinitely; you opt into time-based revalidation, or opt out of caching entirely, per call.

Controlling the Data Cache per fetch call

TSX
// Cached indefinitely (default)
await fetch('https://api.example.com/posts')

// Revalidate at most once every 60 seconds
await fetch('https://api.example.com/posts', { next: { revalidate: 60 } })

// Never cache — always hit the network
await fetch('https://api.example.com/posts', { cache: 'no-store' })
Full Route Cache
At build time (for static routes) Next.js renders a route once and caches the resulting HTML and RSC payload, serving that same output to every visitor until the cache is invalidated — by a new deployment, or by calling revalidatePath/revalidateTag from a Server Action or Route Handler.

Invalidating the Full Route Cache after a mutation

TSX
'use server'

import { revalidatePath } from 'next/cache'

export async function publishPost(id: string) {
  await db.post.update({ where: { id }, data: { published: true } })
  revalidatePath('/blog')
}
Router Cache
The Router Cache lives entirely in the browser. As a user navigates, Next.js caches the RSC payload for visited and prefetched routes so that navigating back to them is instant, without a server round-trip. It's cleared by a full page reload, or by a revalidatePath/revalidateTag call from the server, which invalidates the corresponding client-side entries too.
  • Request Memoization — one render pass, dedupes identical fetch calls within it.

  • Data Cache — server, persists indefinitely by default, controlled per fetch with revalidate/no-store.

  • Full Route Cache — server, caches a static route's rendered output until a deploy or manual revalidation.

  • Router Cache — browser, caches visited/prefetched route payloads for a session.

  • revalidatePath/revalidateTag are the shared tools for clearing the Data Cache and Full Route Cache (and, by extension, the Router Cache entries built from them) on demand.