Next.js Curriculum
MediumData Fetching100% Free25 min read

Request Deduplication & React.cache Internals

The 30-Second Interview Answer

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
Memoization conceptsReact Server Component render passHTTP fetch API

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.ts
2import { cache } from 'react';
3import { db } from '@/lib/db';
4import { users } from '@/lib/schema';
5import { eq } from 'drizzle-orm';
6
7// React.cache memoizes the function call per-request.
8// Multiple components calling getCurrentUser() during the same HTTP request
9// 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 db
13 .select()
14 .from(users)
15 .where(eq(users.id, userId))
16 .limit(1);
17
18 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

Does React.cache() work with primitive and object arguments?

Yes, but it uses Object.is comparison for arguments. If you pass new object references each time, the cache will miss.

`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.

Yes, it works identically in Server Components and Route Handlers for the duration of that request.