---
title: "Server Request Lifecycle"
description: "The server request lifecycle governs how incoming HTTP connections are received, abstracted, processed, and rendered across different runtime environments. It coordinates server initialization, uni..."
last_updated: "2026-09-23T10:52:03.111005+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/server-request-lifecycle"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/next/src/server/base-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts)
- [packages/next/src/server/next-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts)
- [packages/next/src/server/lib/router-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-server.ts)
- [packages/next/src/server/app-render/app-render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx)
- [packages/next/src/server/dev/next-dev-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts)
- [packages/next/src/server/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts)
- [packages/next/src/server/web/adapter.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/adapter.ts)
- [packages/next/src/server/render.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx)
- [packages/next/src/server/base-http/node.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts)
- [packages/next/src/server/base-http/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts)
- [packages/next/src/server/base-http/web.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts)
- [packages/next/src/server/lib/start-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts)
- [packages/next/src/server/request-meta.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts)
- [packages/next/src/server/image-optimizer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts)
- [packages/next/src/server/lib/patch-set-header.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts)
</details>

## Overview

The server request lifecycle governs how incoming HTTP connections are received, abstracted, processed, and rendered across different runtime environments. It coordinates server initialization, uniform request/response encapsulation, metadata tracking, routing pipelines, and rendering execution for both the App and Pages routers, while providing robust error handling and development-mode compilation hooks.

Sources: [packages/next/src/server/base-server.ts:1714-1729](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1714-L1729), [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/request-meta.ts:51-338](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L51-L338), [packages/next/src/server/lib/router-server.ts:371-431](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-server.ts#L371-L431)

## Server Entry and Initialization

### Overview

Incoming HTTP connections are received and initialized through `startServer` or wrapped via `NextServer` and `NextCustomServer` classes. The server establishes network listeners, handles port retries and process cleanups, and delegates incoming socket and request events into router handlers.

Sources: [packages/next/src/server/lib/start-server.ts:184-295](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L295), [packages/next/src/server/next.ts:183-248](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L248)

### Server Initialization and Lifecycle Execution

The startup procedure orchestrates socket binding, worker messaging, and configuration parsing through a deterministic call sequence.

```mermaid
sequenceDiagram
    participant CLI as startServer() / Worker
    participant HTTP as http.createServer()
    participant INIT as getRequestHandlers()
    participant ROUTER as initialize()

    CLI->>HTTP: Create server with requestListener & upgrade handlers
    HTTP->>CLI: server.listen(port, hostname)
    CLI->>INIT: Trigger getRequestHandlers() on 'listening' event
    INIT->>ROUTER: Call initialize(opts)
    ROUTER--YIELD-->CLI: Return requestHandler, upgradeHandler, server
```

Sources: [packages/next/src/server/lib/start-server.ts:139-178](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L139-L178), [packages/next/src/server/lib/start-server.ts:274-321](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L274-L321)

### Server Wrapper Implementations

Next.js provides distinct server wrappers for production execution (`NextServer`), custom server integrations via `import next from 'next'` (`NextCustomServer`), and worker-based process spawning.

| Class / Function | Target Use Case | Key Methods | Sources |
|------------------|-----------------|-------------|---------|
| `NextServer` | `next start` production server wrapper | `getRequestHandler()`, `getServer()`, `prepare()` | [packages/next/src/server/next.ts:183-423](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L423) |
| `NextCustomServer` | Custom servers using `import next from 'next'` | `prepare()`, `getRequestHandler()`, `render()` | [packages/next/src/server/next.ts:425-612](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L425-L612) |
| `startServer` | Standalone server lifecycle runner | `requestListener()`, `server.listen()` | [packages/next/src/server/lib/start-server.ts:184-353](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L353) |

Sources: [packages/next/src/server/next.ts:183-612](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts#L183-L612), [packages/next/src/server/lib/start-server.ts:184-353](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L184-L353)

> [!NOTE]
> During server initialization in development (`isDev`), `startServer` sets up a `Watchpack` instance monitoring configuration files (`CONFIG_FILES`) and distribution directories (`absDistDir`) to trigger an automatic server restart with `RESTART_EXIT_CODE` upon modifications or deletions.

Sources: [packages/next/src/server/lib/start-server.ts:557-608](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L557-L608)

### Request Dispatched Handlers

When an HTTP connection arrives at `requestListener`, requests await the initialization promise (`handlersPromise`) before being passed to `requestHandler`. Upgrade requests are similarly captured and routed through `upgradeHandler`.

```typescript
async function requestListener(req: IncomingMessage, res: ServerResponse) {
  try {
    if (handlersPromise) {
      await handlersPromise
      handlersPromise = undefined
    }
    await requestHandler(req, res)
  } catch (err) {
    res.statusCode = 500
    res.end('Internal Server Error')
    Log.error(`Failed to handle request for ${req.url}`)
    console.error(err)
  }
}
```

Sources: [packages/next/src/server/lib/start-server.ts:240-272](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/start-server.ts#L240-L272)

## HTTP Abstraction and Request Adapters

### Overview

Next.js unifies request and response handling across Node.js and Web standard runtime environments through abstract base classes (`BaseNextRequest` and `BaseNextResponse`) implemented by concrete runtime wrappers (`NodeNextRequest`, `NodeNextResponse`, `WebNextRequest`, and `WebNextResponse`). This encapsulation allows server pipelines to interact with request streams, headers, cookies, and status codes uniformly regardless of whether execution occurs in a Node.js server environment or a Web-standard edge sandbox.

Sources: [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/base-http/node.ts:19-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L169), [packages/next/src/server/base-http/web.ts:11-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L140)

### HTTP Abstraction Architecture

The architecture relies on abstract classes that define common properties and shared utility methods like cookie parsing and redirect helpers, while delegating low-level input/output operations to runtime-specific classes.

| Abstract Class | Concrete Node.js Class | Concrete Web Class | Destination / Underlying Body Type | Sources |
|----------------|------------------------|--------------------|----------------------------------|---------|
| `BaseNextRequest` | `NodeNextRequest` | `WebNextRequest` | Node.js `Readable` stream vs Web `ReadableStream | null` | [packages/next/src/server/base-http/index.ts:28-45](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L45), [packages/next/src/server/base-http/node.ts:19-73](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L73), [packages/next/src/server/base-http/web.ts:11-36](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L36) |
| `BaseNextResponse` | `NodeNextResponse` | `WebNextResponse` | Node.js `Writable` (`ServerResponse`) vs Web `WritableStream` (`TransformStream`) | [packages/next/src/server/base-http/index.ts:47-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L47-L103), [packages/next/src/server/base-http/node.ts:75-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L75-L169), [packages/next/src/server/base-http/web.ts:38-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L38-L140) |

Sources: [packages/next/src/server/base-http/index.ts:28-103](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/index.ts#L28-L103), [packages/next/src/server/base-http/node.ts:19-169](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L19-L169), [packages/next/src/server/base-http/web.ts:11-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L11-L140)

> [!WARNING]
> `NodeNextRequest.stream()` can only be called once. Attempting to consume or convert the Node request body into a Web `ReadableStream` more than once throws an invariant error because the underlying Node.js stream begins flowing immediately upon attaching data handlers.

Sources: [packages/next/src/server/base-http/node.ts:42-72](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/node.ts#L42-L72)

### Web Response Transformation and Lifecycle

In web-standard and edge runtimes, `WebNextResponse` manages output through a `TransformStream` and a `CloseController`. When completing execution, `toResponse()` resolves pending promises, wraps body consumption if listeners are present, and returns a standard Web `Response`.

```typescript
export class WebNextResponse extends BaseNextResponse<WritableStream> {
  private headers = new Headers()
  private textBody: string | undefined = undefined
  private closeController = new CloseController()
  public statusCode: number | undefined
  public statusMessage: string | undefined

  constructor(public transformStream = new TransformStream()) {
    super(transformStream.writable)
  }

  setHeader(name: string, value: string | string[]): this {
    this.headers.delete(name)
    for (const val of Array.isArray(value) ? value : [value]) {
      this.headers.append(name, val)
    }
    return this
  }
}
```

Sources: [packages/next/src/server/base-http/web.ts:38-58](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L38-L58)

> [!CAUTION]
> Calling `onClose()` on a `WebNextResponse` instance that is already closed triggers an `InvariantError`. Lifecycle callbacks must be registered before the response body finishes streaming and the close controller dispatches its close event.

Sources: [packages/next/src/server/base-http/web.ts:132-140](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-http/web.ts#L132-L140)

## Request Metadata and State Tracking

### Overview

Next.js attaches routing context, parsed parameters, incremental cache references, and body cloning state directly to incoming HTTP request objects using a private symbol key. This avoids polluting public request properties while allowing internal modules to share request-scoped data across boundaries.

```typescript
export const NEXT_REQUEST_META = Symbol.for('NextInternalRequestMeta')

export type NextIncomingMessage = (
  | BaseNextRequest
  | IncomingMessage
  | NextRequest
) & {
  [NEXT_REQUEST_META]?: RequestMeta
}
```

Sources: [packages/next/src/server/request-meta.ts:19-27](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L19-L27)

### Request Metadata Operations

State attachment and retrieval are handled by helper functions that read or mutate the record stored under `NEXT_REQUEST_META`.

```typescript
export function getRequestMeta(
  req: NextIncomingMessage,
  key?: undefined
): RequestMeta
export function getRequestMeta<K extends keyof RequestMeta>(
  req: NextIncomingMessage,
  key: K
): RequestMeta[K]
export function getRequestMeta<K extends keyof RequestMeta>(
  req: NextIncomingMessage,
  key?: K
): RequestMeta | RequestMeta[K] {
  const meta = req[NEXT_REQUEST_META] || {}
  return typeof key === 'string' ? meta[key] : meta
}

export function setRequestMeta(req: NextIncomingMessage, meta: RequestMeta) {
  req[NEXT_REQUEST_META] = meta
  return meta
}

export function addRequestMeta<K extends keyof RequestMeta>(
  request: NextIncomingMessage,
  key: K,
  value: RequestMeta[K]
) {
  const meta = getRequestMeta(request)
  meta[key] = value
  return setRequestMeta(request, meta)
}

export function removeRequestMeta<K extends keyof RequestMeta>(
  request: NextIncomingMessage,
  key: K
) {
  const meta = getRequestMeta(request)
  delete meta[key]
  return setRequestMeta(request, meta)
}
```

Sources: [packages/next/src/server/request-meta.ts:348-408](https://github.com/blade47/next.js/blob/main/packages/next/src/server/request-meta.ts#L348-L408)

### Header Patching and Cookie Support

To prevent headers set by middleware from being overwritten or dropped by downstream API routes or `getServerSideProps`, Next.js patches the response object's `setHeader` method.

```typescript
export function patchSetHeaderWithCookieSupport(
  req: NextIncomingMessage,
  res: PatchableResponse
) {
  if (res[PATCHED_SET_HEADER]) {
    return
  }

  const setHeader = res.setHeader.bind(res)

  Object.defineProperty(res, PATCHED_SET_HEADER, {
    value: true,
  })

  res.setHeader = (
    name: string,
    value: string | string[]
  ): PatchableResponse => {
    if ('headersSent' in res && res.headersSent) {
      return res
    }

    if (name.toLowerCase() === 'set-cookie') {
      const middlewareValue = getRequestMeta(req, 'middlewareCookie')

      if (
        !middlewareValue ||
        !Array.isArray(value) ||
        !value.every((item, idx) => item === middlewareValue[idx])
      ) {
        value = [
          ...new Set([
            ...(middlewareValue || []),
            ...(typeof value === 'string'
              ? [value]
              : Array.isArray(value)
                ? value
                : []),
          ]),
        ]
      }
    }

    return setHeader(name, value)
  }
}
```

Sources: [packages/next/src/server/lib/patch-set-header.ts:18-66](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts#L18-L66)

> [!NOTE]
> `patchSetHeaderWithCookieSupport` uses a symbol flag `PATCHED_SET_HEADER` to guarantee that the response object is patched at most once per request, avoiding recursive wrapper overhead when multiple handlers invoke `setHeader`.

Sources: [packages/next/src/server/lib/patch-set-header.ts:3-24](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-set-header.ts#L3-L24)

## Server Request Pipeline (`NextServer` / `NextNodeServer`)

### Overview

Server classes coordinate the core request handling loop, URL normalization, locale analysis, and routing execution for Next.js applications. Incoming requests flow through normalization routines that filter pathname information, inspect specialized request markers, and execute tracing spans.

Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661), [packages/next/src/server/base-server.ts:1747-1764](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1747-L1764)

### Pathname Normalization and Metadata

Pathnames are normalized using an ordered array of normalizers checked sequentially. If a normalizer matches the pathname, its normalization logic is applied directly.

```typescript
  private normalize = (pathname: string) => {
    const normalizers: Array<PathnameNormalizer> = []

    if (this.normalizers.data) {
      normalizers.push(this.normalizers.data)
    }

    // We have to put the segment prefetch normalizer before the RSC normalizer
    // because the RSC normalizer will match the prefetch RSC routes too.
    if (this.normalizers.segmentPrefetchRSC) {
      normalizers.push(this.normalizers.segmentPrefetchRSC)
    }

    if (this.normalizers.rsc) {
      normalizers.push(this.normalizers.rsc)
    }

    for (const normalizer of normalizers) {
      if (!normalizer.match(pathname)) continue

      return normalizer.normalize(pathname, true)
    }

    return pathname
  }
```

Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661)

> [!CAUTION]
> The segment prefetch normalizer must be evaluated before the React Server Components (RSC) normalizer in the array. Because the RSC normalizer matches prefetch RSC routes as well, placing it first would intercept and misroute segment prefetches.

Sources: [packages/next/src/server/base-server.ts:1644-1648](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1644-L1648)

### Request Pipeline Execution Walkthrough

The request handling pipeline coordinates tracing spans, streaming context construction, and execution routing:

1. `run()` / `runImpl()`: Wraps execution within tracing spans and dispatches the catch-all render request handler.
2. `pipe()` / `pipeImpl()`: Inspects the user-agent header, creates a cloned `RequestContext` with `supportsDynamicResponse` based on bot detection status, and determines whether streaming metadata should be served.
3. `normalizeAndAttachMetadata()`: Evaluates specialized request handlers like image optimization and pages data endpoints before standard routing.

Sources: [packages/next/src/server/base-server.ts:1663-1676](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1663-L1676), [packages/next/src/server/base-server.ts:1747-1763](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1747-L1763), [packages/next/src/server/base-server.ts:1765-1804](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1765-L1804)

### Pipeline Constants and Design Choices

| Design Choice | Benefit | Cost |
| --- | --- | --- |
| Sequential normalizer array evaluation | Deterministic matching order for overlapping patterns like RSC and segment prefetches | Linear search overhead across registered normalizers per request |
| Centralized tracing via `BaseServerSpan` | Detailed OpenTelemetry instrumentation across request lifecycles | Additional wrapper allocation per pipeline phase |
| Lazy instrumentation loading during `prepare()` | Avoids blocking server startup when instrumentation is absent | Deferred module resolution check until initialization completes |

Sources: [packages/next/src/server/base-server.ts:1637-1661](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1637-L1661), [packages/next/src/server/base-server.ts:1714-1728](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1714-L1728), [packages/next/src/server/base-server.ts:1751-1754](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1751-L1754)

## NextNodeServer Dispatch and Route Execution

### Overview

NextNodeServer orchestrates concrete request routing and dispatch for Pages API routes, internal error pages, and image optimization pipelines. When an incoming request targets an API endpoint, `handleApiRequest` delegates execution directly to `runApi`. Similarly, internal rendering errors or specialized fallback routes trigger specific handler branches like `renderErrorToResponseImpl`, which evaluates edge function availability for special entries such as `UNDERSCORE_NOT_FOUND_ROUTE_ENTRY`.

Sources: [packages/next/src/server/next-server.ts:1232-1239](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1232-L1239), [packages/next/src/server/next-server.ts:1356-1384](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next-server.ts#L1356-L1384)

### Image Optimization Dispatch and Cache Flow

The image optimization subsystem processes requests via `ImageOptimizerCache` and `imageOptimizer`. It validates parameters, manages LRU disk caches or custom cache handlers, and executes image transformations.

```typescript
export async function imageOptimizer(
  imageUpstream: ImageUpstream,
  paramsResult: Pick<ImageParamsResult, 'href' | 'width' | 'quality' | 'mimeType'>,
  nextConfig: { ... },
  opts: { isDev?: boolean; silent?: boolean; previousCacheEntry?: IncrementalResponseCacheEntry | null }
) {
  const { href, quality, width, mimeType } = paramsResult
  const { buffer: upstreamBuffer, etag: upstreamEtag } = imageUpstream
  const maxAge = Math.max(nextConfig.images.minimumCacheTTL, getMaxAge(imageUpstream.cacheControl))
  // Detects content type, validates SVG policies, handles animated/bypass types, and optimizes buffer
}
```

Sources: [packages/next/src/server/image-optimizer.ts:1056-1095](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1056-L1095)

### Image Optimization Execution Walkthrough

The image request processing pipeline moves through specific validation, fetching, and transformation stages:

1. `ImageOptimizerCache.validateParams()`: Inspects query parameters `url`, `w`, and `q`, verifying domain whitelist rules, local patterns, and numerical size constraints.
2. `fetchExternalImage()` / `fetchInternalImage()`: Fetches the upstream resource while checking IP restrictions, response body size limits, and redirect thresholds.
3. `imageOptimizer()`: Inspects magic numbers via `detectContentType()`, checks SVG permissions, bypasses animated or raw image types, and runs `optimizeImage()` using Sharp.
4. `sendResponse()`: Sets response headers such as `Cache-Control`, `Vary: Accept`, `Content-Disposition`, and `X-Nextjs-Cache` before streaming the optimized buffer.

Sources: [packages/next/src/server/image-optimizer.ts:387-549](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L387-L549), [packages/next/src/server/image-optimizer.ts:872-1054](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L872-L1054), [packages/next/src/server/image-optimizer.ts:1056-1236](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1056-L1236), [packages/next/src/server/image-optimizer.ts:1292-1327](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L1292-L1327)

### Image Optimization Constants and Validation Flags

| Constant / Array | Values / Types | Purpose |
| --- | --- | --- |
| `ANIMATABLE_TYPES` | `['image/webp', 'image/png', 'image/gif']` | Formats checked for animation frames that bypass optimization |
| `BYPASS_TYPES` | `['image/svg+xml', 'image/x-icon', 'image/x-icns', 'image/bmp', 'image/jxl', 'image/heic']` | Formats returned directly without running the sharp transformer |
| `CACHE_VERSION` | `4` | Version identifier embedded into image cache key generation hashes |
| `BLUR_IMG_SIZE` | `8` | Default width assigned to generated blur placeholder images |

Sources: [packages/next/src/server/image-optimizer.ts:42-60](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L42-L60)

> [!WARNING]
> Requesting an external image whose hostname resolves to a private IP address will trigger a 400 error and throw an `ImageError`, unless `images.dangerouslyAllowLocalIP` is explicitly enabled in configuration.

Sources: [packages/next/src/server/image-optimizer.ts:878-900](https://github.com/blade47/next.js/blob/main/packages/next/src/server/image-optimizer.ts#L878-L900)

## Page and App Render Dispatch

### Overview

The rendering dispatcher coordinates payload generation across both the Pages router (via React Fizz/SSR and `renderToHTMLImpl`) and the App Router (via React Flight streaming and server component rendering trees). The server pipeline constructs execution contexts, evaluates headers such as `NEXT_ROUTER_PREFETCH_HEADER` and `RSC_HEADER`, and delegates execution down to specific module renderers.

Sources: [packages/next/src/server/base-server.ts:1765-1804](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1765-L1804), [packages/next/src/server/app-render/app-render.tsx:395-470](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L395-L470), [packages/next/src/server/render.tsx:459-468](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L459-L468)

### Header Parsing and Request Modifiers

When a rendering request hits the server, `parseRequestHeaders()` inspects incoming HTTP headers to establish the exact rendering intent, distinguishing between standard RSC navigation, prefetch variants, and HMR refreshes.

```typescript
function parseRequestHeaders(
  headers: IncomingHttpHeaders,
  options: ParseRequestHeadersOptions
): ParsedRequestHeaders {
  const isPrefetchRequest = headers[NEXT_ROUTER_PREFETCH_HEADER] === '1'
  const isAppShellPrefetchRequest = headers[NEXT_ROUTER_PREFETCH_HEADER] === '3'
  const isRuntimePrefetchRequest =
    headers[NEXT_ROUTER_PREFETCH_HEADER] === '2' || isAppShellPrefetchRequest
  const isHmrRefresh = headers[NEXT_HMR_REFRESH_HEADER] !== undefined
  const isRSCRequest = isRSCRequestHeader(headers[RSC_HEADER])
  // ...
```

Sources: [packages/next/src/server/app-render/app-render.tsx:395-414](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L395-L414)

### Render Options and Pipeline Execution

The `pipe()` and `pipeImpl()` methods manage request context construction, appending bot detection parameters and streaming metadata flags before executing the render delegate.

```typescript
  private async pipeImpl(
    fn: (
      ctx: RequestContext<ServerRequest, ServerResponse>
    ) => Promise<ResponsePayload | null>,
    partialContext: Omit<
      RequestContext<ServerRequest, ServerResponse>,
      'renderOpts'
    >
  ): Promise<void> {
    const ua = partialContext.req.headers['user-agent'] || ''

    const ctx: RequestContext<ServerRequest, ServerResponse> = {
      ...partialContext,
      renderOpts: {
        ...this.renderOpts,
        supportsDynamicResponse: !this.renderOpts.botType,
        serveStreamingMetadata: shouldServeStreamingMetadata(
          ua,
          this.nextConfig.htmlLimitedBots
        ),
      },
    }

    const payload = await fn(ctx)
```

Sources: [packages/next/src/server/base-server.ts:1779-1803](https://github.com/blade47/next.js/blob/main/packages/next/src/server/base-server.ts#L1779-L1803)

### Parsed Request Header Constants

| Header Constant | Header Name / Value Condition | Purpose |
| --- | --- | --- |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'1'` | Identifies standard client-side router prefetch requests |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'2'` | Identifies runtime prefetch requests |
| `NEXT_ROUTER_PREFETCH_HEADER` | `'3'` | Identifies App Shell prefetch (omits link data and parameters) |
| `NEXT_HMR_REFRESH_HEADER` | `undefined` check | Detects HMR refresh events during development rendering |
| `RSC_HEADER` | Checked via `isRSCRequestHeader()` | Identifies React Server Component payload streams |

Sources: [packages/next/src/server/app-render/app-render.tsx:401-413](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L401-L413)

### Render Pipeline Design Trade-Offs

| Design Choice | Benefit | Cost |
| --- | --- | --- |
| Separate `renderToHTMLImpl` and Flight stream handlers | Isolates Pages router Fizz/SSR rendering logic from App Router streaming architectures | Duplicates context preparation wiring across different routing paradigms |
| Strict header-based prefetch classification (`1`, `2`, `3`) | Prevents unnecessary data resolution during shell and runtime prefetches | Requires careful client/server header synchronization |
| Dynamic stale time tree-walking (`getDynamicStaleTime`) | Avoids full server component rendering when extracting static segment configs | Recursively inspects module definitions prior to handling requests |

Sources: [packages/next/src/server/app-render/app-render.tsx:482-512](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L482-L512), [packages/next/src/server/render.tsx:459-468](https://github.com/blade47/next.js/blob/main/packages/next/src/server/render.tsx#L459-L468)

> [!NOTE]
> App Shell prefetches (where `NEXT_ROUTER_PREFETCH_HEADER` is set to `'3'`) omit dynamic parameter resolution during server rendering. Any attempt to await `params` inside an App Shell prefetch will hang indefinitely, producing a param-independent shell of the route.

Sources: [packages/next/src/server/app-render/app-render.tsx:380-385](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L380-L385), [packages/next/src/server/app-render/app-render.tsx:403-404](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/app-render.tsx#L403-L404)

## Development Server and Error Handling

### Overview

Development-mode execution in Next.js wraps standard request routing with performance instrumentation, memory tracking, on-demand compilation triggers, and enhanced error stack formatting. Development server implementations override core request handlers to ensure bundler service integration and error overlays operate transparently during local development.

Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591), [packages/next/src/server/dev/next-dev-server.ts:624-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L624-L642)

### Dev-Mode Request Interception and Telemetry

Incoming requests in the development server pass through `handleRequest()`, which initiates a performance trace span (`handle-request`), waits for server readiness via `this.ready?.promise`, and attaches debug flags such as `PagesErrorDebug`. Upon completion, RSS and heap metrics are captured via `process.memoryUsage()` and logged as child telemetry spans.

```typescript
  public async handleRequest(
    req: NodeNextRequest,
    res: NodeNextResponse,
    parsedUrl?: NextUrlWithParsedQuery
  ): Promise<void> {
    const span = trace('handle-request', undefined, { url: req.url })
    const result = await span.traceAsyncFn(async () => {
      await this.ready?.promise
      addRequestMeta(req, 'PagesErrorDebug', this.renderOpts.ErrorDebug)
      return await super.handleRequest(req, res, parsedUrl)
    })
    const memoryUsage = process.memoryUsage()
    span
      .traceChild('memory-usage', {
        url: req.url,
        'memory.rss': String(memoryUsage.rss),
        'memory.heapUsed': String(memoryUsage.heapUsed),
        'memory.heapTotal': String(memoryUsage.heapTotal),
      })
      .stop()
    return result
  }
```

Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591)

> [!WARNING]
> Unhandled errors thrown during `run()` in development servers are passed through `getProperError()`, formatted via `formatServerError()`, and dispatched to `logErrorWithOriginalStack()` before triggering `renderError()`. If headers have already been sent, the response status is forced to `500` with an emergency text fallback.

Sources: [packages/next/src/server/dev/next-dev-server.ts:624-642](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L624-L642)

### Instrumentation Hooks and On-Demand Compilation

The development server manages module compilation and telemetry initialization through lifecycle hooks. `loadInstrumentationModule()` checks for the presence of an instrumentation hook file, ensures it is compiled via `ensurePage()`, and retrieves the module via `getInstrumentationModule()`.

```typescript
  protected async loadInstrumentationModule(): Promise<any> {
    let instrumentationModule: any
    if (
      this.actualInstrumentationHookFile &&
      (await this.ensurePage({
        page: this.actualInstrumentationHookFile!,
        clientOnly: false,
        definition: undefined,
      })
        .then(() => true)
        .catch(() => false))
    ) {
      try {
        instrumentationModule = await getInstrumentationModule(
          this.dir,
          this.nextConfig.distDir
        )
      } catch (err: any) {
        err.message = `An error occurred while loading instrumentation hook: ${err.message}`
        throw err
      }
    }
    return instrumentationModule
  }
```

Sources: [packages/next/src/server/dev/next-dev-server.ts:714-737](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L714-L737)

### Development Server Methods and Fallback Signatures

| Method Name | Return Type | Purpose |
| --- | --- | --- |
| `handleRequest` | `Promise<void>` | Traces dev requests, verifies server readiness, and appends memory usage spans |
| `run` | `Promise<void>` | Strips basePath prefixes, dispatches execution to `super.run`, and catches unhandled render errors |
| `logErrorWithOriginalStack` | `void` | Delegates stack frame mapping to `this.bundlerService` |
| `loadInstrumentationModule` | `Promise<any>` | Ensures and loads the user instrumentation file from the distribution directory |
| `ensureEdgeFunction` | `Promise<void>` | Triggers on-demand compilation for Edge runtime worker targets |

Sources: [packages/next/src/server/dev/next-dev-server.ts:570-591](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L570-L591), [packages/next/src/server/dev/next-dev-server.ts:644-649](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L644-L649), [packages/next/src/server/dev/next-dev-server.ts:714-759](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/next-dev-server.ts#L714-L759)

## Related

- [Routing and Normalization](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/routing-and-normalization)
- [Route Matching](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/server-runtime/route-matching)
- [App Server Rendering](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/app-router-rendering/app-server-rendering)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
