Data Caching
Next.js maintains a server-side Data Cache that stores the results of fetch calls. Unlike an in-memory cache that resets on every request, the Data Cache persists across incoming requests and, by default, across deployments — making it a durable, shared cache for the data your app fetches.
How fetch options interact with the Data Cache
Whether a given fetch call is stored in, read from, or skipped by the Data Cache depends entirely on the options you pass to it (or the route segment config it inherits).
// Stored indefinitely, reused on every future matching request
await fetch(url, { cache: 'force-cache' })
// Never touches the Data Cache — always a fresh network request
await fetch(url, { cache: 'no-store' })
// Stored, but considered stale after 60 seconds and eligible for regeneration
await fetch(url, { next: { revalidate: 60 } })
// Stored and associated with a tag for later on-demand invalidation
await fetch(url, { next: { tags: ['products'] } })Two fetch calls with identical URL and options are treated as the same cache entry — the second call reuses the first call's stored response rather than hitting the network again, as long as the entry is still considered fresh.
Data Cache vs. Full Route Cache vs. Router Cache
Next.js actually layers several caches on top of each other, and it is easy to conflate them. The Data Cache is only one of the three most relevant to the App Router.
Cache | What it stores | Where it lives | Cleared by |
|---|---|---|---|
Data Cache | Results of individual fetch() calls | Server | revalidatePath, revalidateTag, cache: "no-store", or the configured revalidate window elapsing |
Full Route Cache | The rendered HTML + RSC payload for a whole static route | Server | A new deployment, or revalidation of the underlying data it depends on |
Router Cache (client-side) | RSC payloads for routes the user has already visited in this session | Browser (in-memory) | A full page reload, or a set duration passing, depending on route type |
The Full Route Cache builds on top of the Data Cache: if every fetch in a route is cacheable, Next.js can cache the entire rendered route, not just the individual data responses. Invalidating the underlying data (via revalidatePath/revalidateTag, or the revalidate window) also invalidates the Full Route Cache for that route.
Opting out per fetch vs. per route
You can control caching at the individual fetch call, as shown above, or for an entire route segment by exporting configuration from a page or layout file — useful when a whole route should never be cached, for example one that always shows account-specific data.
// Opts this entire route out of the Data Cache and the Full Route Cache export const dynamic = 'force-dynamic'