- Next.js
- Data Fetching & Request Lifecycle
- Request Deduplication & React.cache Internals
Request Deduplication & React.cache Internals
Request deduplication ensures that identical data requests within a single server render cycle execute only once. Native fetch() requests with identical URLs and options are deduplicated automatically by Next.js. For non-fetch operations (Prisma, Drizzle, raw DB queries, internal calculations), React provides the cache() utility to memoize results per-request lifecycle.
Learning Objectives
Understand how Next.js monkey-patches native fetch() for per-request deduplication.
Wrap database and ORM queries using React.cache() to prevent redundant database roundtrips.
Explain the request-scoped lifecycle of React.cache() versus persistent caching.
Avoid prop drilling across layout.tsx, page.tsx, and deeply nested Server Components.
Prerequisites & Background Knowledge
Why Interviewers Care
Tests candidate understanding of performance optimization, data layer design, and component encapsulation in large-scale applications.
The Challenge
How does Next.js handle request deduplication during a single server render pass? When must you use React.cache(), and how does its lifecycle differ from persistent caching mechanisms?
Code Architecture & Implementation
1// lib/data-access/user.ts2import { cache } from 'react';3import { db } from '@/lib/db';4import { users } from '@/lib/schema';5import { eq } from 'drizzle-orm';67// React.cache memoizes the function call per-request.8// Multiple components calling getCurrentUser() during the same HTTP request9// trigger the database query EXACTLY ONCE!10export const getCurrentUser = cache(async (userId: string) => {11 console.log(`[DB QUERY] Executing query for user: ${userId}`);12 const [user] = await db13 .select()14 .from(users)15 .where(eq(users.id, userId))16 .limit(1);1718 return user ?? null;19});
Architectural Explanation
In React Server Components, child components should be autonomous and fetch their own required data rather than relying on top-level layouts to fetch everything and pass props down through 10 layers. To make this safe, React created React.cache(). It takes a function and returns a memoized version that stores results in a request-scoped cache. Once the HTTP response is sent, the cache is garbage-collected. This is distinct from persistent caches (like Data Cache or Redis) which persist across different user requests.
Common Mistakes & Anti-Patterns
Assuming React.cache() caches data across multiple users or page reloads (it does not; it is strictly per-request).
Using React.cache() in Client Components (it is intended for Server Components).
Prop-drilling data from root layout down to deep leaf components out of fear of duplicate queries.
Interview Follow-Up Traps
The interviewer asks: "If I call fetch() with method: POST, does Next.js deduplicate it?" No! Next.js only deduplicates GET requests. POST/PUT/DELETE requests represent mutations and are never memoized.
Frequently Asked Questions
How does React.cache() differ from React.useMemo()?
`useMemo` runs on the client across re-renders of a single component instance. `React.cache()` runs on the server across multiple components during a single HTTP request lifecycle.
Can React.cache() be used in Route Handlers?
Yes, it works identically in Server Components and Route Handlers for the duration of that request.
