This article was originally published on the previous Kolarclub website on 24 April 2025. It was transferred here on 22 July 2026 and lightly revised for clarity and technical accuracy.
Next.js 15 App Router has several caching layers, each with a different scope:
- Request Memoization — reuses matching requests during a single React render.
- Data Cache — stores data across incoming requests.
- Full Route Cache — stores the rendered HTML and React Server Component payload for static routes.
- Router Cache — stores route segments in the browser during navigation.
- React
cache— memoizes a function during server rendering whenfetchis not the right tool.
This first part focuses on request memoization.
What Request Memoization Does
During a server render, React automatically deduplicates matching GET and HEAD calls made with fetch. If the same URL and options are used more than once, only the first call performs the network request. Later calls in that render receive the memoized result.
async function getPost() {
const response = await fetch('https://example.com/api/posts/1')
return response.json()
}
async function PostTitle() {
const post = await getPost() // network request
return <h1>{post.title}</h1>
}
async function PostSummary() {
const post = await getPost() // memoized result
return <p>{post.summary}</p>
}
export default function Page() {
return (
<>
<PostTitle />
<PostSummary />
</>
)
}
The two components can fetch the data where they need it without moving the request to a common parent purely to avoid duplication.

Matching requests from layouts, pages, metadata, and components are deduplicated during the render.
Scope and Lifetime
Request memoization is deliberately short-lived:

The first matching fetch stores its result in memory; later calls reuse it until the render finishes.
- It lasts only for the current React server render.
- Its entries are cleared after the render completes.
- It applies to Server Components, layouts, pages,
generateMetadata, andgenerateStaticParams. - It does not apply to Route Handlers because they are outside the React component tree.
- It works during static rendering, dynamic rendering, and an ISR regeneration pass.
This is different from the Data Cache, which can reuse a result across different visitors and deployments.
Memoization Is Not Persistent Caching
An uncached request can still be memoized within one render:
const response = await fetch('https://example.com/api/posts/1', {
cache: 'no-store',
})
With this configuration, the first matching call in every render reaches the data source. Duplicate calls made during that same render still reuse the result.
That distinction is useful:
- Request Memoization prevents duplicate work inside one render.
- Data Cache prevents repeated work across separate requests.
Using React cache Without fetch
For a database, CMS SDK, or another data source that does not use fetch, wrap the data-access function with React’s cache:
import { cache } from 'react'
import { db } from '@/lib/db'
export const getPost = cache(async (id: string) => {
return db.post.findUnique({ where: { id } })
})
Calls to getPost with the same argument can then share a result during the same server render.
What It Does Not Replace
Request memoization can remove unnecessary prop drilling when several Server Components need the same server data. It does not replace Redux, Zustand, or other client-state tools in general.
Client state still has a different job: it tracks interactive state in the browser, coordinates client-side updates, and can persist beyond one server render.
Important Limits
- Matching means the URL and request options must be the same.
- Mutation requests such as
POST,PUT, andDELETEare not memoized. - Memoization is a React rendering optimization, not a durable application cache.
- Passing an
AbortSignalopts an individual request out of automatic memoization.
Why It Matters
Request memoization lets components remain self-contained without paying for the same network request several times during one render. Once its per-render scope is clear, it becomes easier to decide whether a problem needs memoization, the persistent Data Cache, or client-side state.
For the full behavior and current caveats, see the Next.js 15 caching guide.