Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteOften the answer is no, at least not in the sense the title suggests. In the Next.js App Router, identical fetch requests made from generateMetadata and from a page component are memoized during the same render, so Next.js deduplicates them. A direct database or ORM query does not get that treatment automatically. For those, you route both callers through one function wrapped with React’s cache. The distinction that matters most is this: request memoization works within a single render. It is not a cache that persists across requests, and it does not decide how fresh your data is.
What “twice” actually means here
Seeing two calls to the same helper in your source code does not prove that the data is fetched twice at runtime. Two things can look identical in code but behave differently. A fetch call is handled by Next.js, which can reuse the result of an identical request during a render. A function that queries a database is just your code, and React and Next.js do not reuse its result unless you ask them to. Work out which of the two you are dealing with before you change anything.
As an Amazon Associate I earn from qualifying purchases.
Case 1: the data comes from fetch
The Next.js reference for generateMetadata, last updated March 25, 2026, states that fetch requests inside generateMetadata are automatically memoized for the same data across generateMetadata, generateStaticParams, Layouts, Pages, and Server Components. The practical steps are:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware match- Write the request the same way in both places, or move it into one helper that both files import.
- Check that the URL and every option match exactly. A different header, query string, or cache option makes the requests different, and the framework documentation does not establish that non-identical requests deduplicate.
- Call it from both
generateMetadataand the page component. Next.js memoizes the identical request during the render, so you do not need to pass the result down through props.
// lib/posts.ts
export async function getPost(slug: string) {
const res = await fetch(`https://api.example.com/posts/${slug}`)
if (!res.ok) throw new Error(`Failed to load post ${slug}`)
return res.json()
}
Both generateMetadata and the page can then call getPost(slug). The URL and options are identical, so the request is memoized. Note that the helper function itself still runs twice. What gets deduplicated is the network request beneath it, so a log line inside the helper will show two calls even when only one request is sent.
#1 Best Overall
Case 2: the data comes from an ORM or database client
Database clients are not fetch, so the automatic memoization does not apply to them. The Next.js guide on metadata demonstrates the fix: wrap the query in React’s cache and call the wrapped function from both places. The guide’s example says the function is used twice but executes once.
import { cache } from 'react'
import { db } from '@/app/lib/db'
export const getPost = cache(async (slug: string) => {
return db.query.posts.findFirst({ where: eq(posts.slug, slug) })
})
Keep three rules in mind. Both callers must import the same wrapped function from the same module, because wrapping a second copy creates a second cache. Both must pass the same arguments, since the result is keyed on them. And the wrapper is only worth adding where a query is actually shared; wrapping every query by reflex adds indirection without a benefit.
Rank #2
Memoization is not persistent caching
This is the point most likely to cause bugs when people act on “they are the same data.” Request memoization removes repeated work within one render. It does not store responses for later visitors or later requests. The Next.js fetching guide distinguishes the two and states that fetch responses are not persistently cached by default.
| Mechanism | What it covers | Lifetime | Default behavior |
|---|---|---|---|
| Fetch request memoization | Identical fetch requests across generateMetadata, generateStaticParams, layouts, pages, and Server Components |
Within the render | On, per the Next.js fetching guide and generateMetadata reference |
React cache wrapper |
Your own function, such as an ORM query, called with the same arguments | Within the render | Off until you wrap the function |
| Persistent fetch caching | Stored responses reused across later requests | Set by your caching configuration | Not cached by default, per the Next.js fetching guide |
If the data should be reused across requests, choose a persistent caching policy deliberately and document it. If the data must be current on every visit, do not add a longer-lived cache to reduce duplicate calls. Deduplication within the render is compatible with fresh data; persistent caching is a separate decision.
Rank #3
Static metadata or generateMetadata
Before optimizing the call, check whether you need generateMetadata at all. The metadata guide, last updated February 27, 2026, recommends the static metadata export when values do not depend on runtime information.
- Use the static
metadataobject when the title and description are fixed, or come from constants and configuration. - Use
generateMetadatawhen the metadata depends on route params or external data, such as a post title loaded from a CMS. - Keep both in Server Components.
metadataandgenerateMetadataare supported only in Server Components, so they cannot be exported from a Client Component.
Cache Components and runtime data in metadata
If you have Cache Components enabled, metadata behaves differently. When generateMetadata reads runtime or uncached data, it can affect how the route is prerendered. A route whose body could otherwise be fully prerendered may then need one of two explicit choices.
- Cache the data where that is appropriate, so the metadata can be prerendered.
- Signal intentional dynamic rendering for the route, so the dynamic behavior is a choice rather than a side effect of the metadata.
Check this before you assume the duplicated calls are the main issue. A route can be slow or dynamic because of the metadata’s data access, even when the page’s own data is already shared correctly.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Checking what actually runs
Verify the behavior in your own project rather than relying on a general rule.
- Add a temporary log line at the top of your ORM wrapper, then load a post. Two log lines with one query result in the logs mean the wrapper is not being shared, and a single line means it is.
- For a
fetch-based helper, put the log on the upstream side, such as the API’s own request logs. The helper’s log will show two calls even when only one network request is made. - Remove the temporary logging once you have confirmed the behavior.
Common mistakes that cause real duplicate work
- Assuming every repeated function call is deduplicated. Only identical
fetchrequests get automatic memoization; direct database access needs a sharedcachewrapper. - Creating a second wrapped function in a different file, which gives each caller its own cache.
- Passing different arguments, or building the same URL with different options, so the requests are not identical.
- Treating request memoization as persistent caching and assuming data is kept between visitors.
- Exporting
generateMetadatafrom a Client Component. - Reading uncached runtime data in metadata with Cache Components enabled, and not addressing the prerendering effect.
Versions and currency
Next.js behavior is version-sensitive. The guidance above follows the current App Router documentation, including the generateMetadata reference (last updated March 25, 2026), the metadata guide (last updated February 27, 2026), and the fetching and Cache Components guides. Check the installed Next.js version in your project’s package.json against the docs for that version before assuming these behaviors hold in older releases.
Quick Recap
“
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




