Next.js Curriculum
MediumData Fetching100% Free30 min read

Breaking Change: Async Request APIs in Next.js 15+

The 30-Second Interview Answer

In Next.js 15+, dynamic request data—specifically params, searchParams, cookies(), and headers()—is asynchronous and must be awaited. This architectural breaking change allows Next.js to start prerendering static page shells before the server even receives the incoming HTTP request headers or URL parameters, forming the foundation for Partial Prerendering (PPR).

Learning Objectives

Understand the migration from synchronous params and searchParams to async Promises.

Refactor cookies() and headers() calls to await them in Server Components and Route Handlers.

Explain how async request APIs unlock Partial Prerendering (PPR) and earlier static shell generation.

Use React.use() to unwrap params and searchParams in Client Components.

Prerequisites & Background Knowledge
Next.js App Router routingJavaScript Promises and async/awaitPartial Prerendering concepts

Why Interviewers Care

Critical for senior Next.js interviews. Demonstrates up-to-date knowledge of Next.js 15/16 breaking changes and architectural optimizations.

The Challenge

Why did Next.js 15 make params, searchParams, cookies(), and headers() asynchronous? Demonstrate how to access dynamic segment parameters and read cookies in both Server Components and Client Components.

Code Architecture & Implementation

1// app/products/[category]/[slug]/page.tsx
2import { cookies, headers } from 'next/headers';
3
4interface PageProps {
5 // In Next.js 15+, params and searchParams are Promises!
6 params: Promise<{ category: string; slug: string }>;
7 searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
8}
9
10export default async function ProductDetailPage({ params, searchParams }: PageProps) {
11 // 1. Await route parameters
12 const { category, slug } = await params;
13
14 // 2. Await search parameters
15 const query = await searchParams;
16 const sort = query.sort ?? 'featured';
17
18 // 3. Await headers and cookies
19 const cookieStore = await cookies();
20 const theme = cookieStore.get('theme')?.value ?? 'light';
21
22 const headerList = await headers();
23 const userAgent = headerList.get('user-agent') ?? 'unknown';
24
25 return (
26 <div>
27 <h1>Product: {slug} ({category})</h1>
28 <p>Sort: {String(sort)} | Theme: {theme}</p>
29 </div>
30 );
31}

Architectural Explanation

Historically, reading cookies() or accessing params synchronously forced Next.js to wait for the incoming request before beginning any rendering work. By making these APIs return Promises, the Next.js runtime can begin prerendering static components, layouts, and Flight trees immediately. When the server reaches an unawaited async request API, only that specific branch pauses or switches to dynamic streaming. This architecture is what enables Partial Prerendering (PPR) to serve static shells in sub-10ms.

Common Mistakes & Anti-Patterns

Accessing `params.slug` without `await`, resulting in runtime warnings or `[object Promise]` rendered in HTML.

Calling `cookies().get("session")` synchronously instead of `(await cookies()).get("session")`.

Forgetting that `searchParams` on pages is also a Promise in Next.js 15+.

Interview Follow-Up Traps

Interviewers will ask: "Does making params async mean route parameters are fetched over the network?" No! Route parameters are parsed in-memory from the URL; they are async so React can defer reading them and prerender static shells before the request arrives.

Frequently Asked Questions

Can I still use synchronous params in Next.js 15?

Next.js 15 provides temporary backward compatibility with console warnings in development, but synchronous access is completely removed in Next.js 16.

Run `npx @next/codemod@latest next-async-request-api .` in the terminal.

The props passed to `generateMetadata({ params, searchParams })` are also Promises and must be awaited.