---
title: "Telemetry and Diagnostics"
description: "Next.js incorporates a unified telemetry and diagnostics subsystem designed to collect anonymous build and development usage metrics, track process memory performance, record garbage collection sta..."
last_updated: "2026-09-23T10:52:03.144385+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/build-and-config/telemetry-and-diagnostics"
---

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

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

- [packages/next/src/cli/next-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-info.ts)
- [packages/next/src/diagnostics/build-diagnostics.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/diagnostics/build-diagnostics.ts)
- [packages/next/src/telemetry/storage.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts)
- [packages/next/src/lib/memory/shutdown.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/shutdown.ts)
- [packages/next/src/lib/memory/trace.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/trace.ts)
- [packages/next/src/telemetry/events/build.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/events/build.ts)
- [packages/next/src/trace/report/to-telemetry.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/report/to-telemetry.ts)
- [packages/next/src/lib/memory/gc-observer.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/gc-observer.ts)
- [packages/next/src/cli/next-telemetry.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-telemetry.ts)
- [packages/next/src/telemetry/flush-telemetry.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/flush-telemetry.ts)
- [packages/next/src/lib/memory/startup.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/startup.ts)
- [packages/next/src/telemetry/events/swc-load-failure.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/events/swc-load-failure.ts)
- [packages/next/src/server/mcp/mcp-telemetry-tracker.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/mcp-telemetry-tracker.ts)
- [packages/next/src/telemetry/detached-flush.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/detached-flush.ts)
- [packages/next/src/cli/internal/upload-trace.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/upload-trace.ts)
- [packages/next/src/telemetry/anonymous-meta.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/anonymous-meta.ts)
- [packages/next/src/server/mcp/tools/get-page-metadata.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/tools/get-page-metadata.ts)
- [packages/next/src/trace/trace-uploader.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/trace-uploader.ts)
- [packages/next/src/server/client-component-renderer-logger.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/client-component-renderer-logger.ts)
- [packages/next/src/next-devtools/userspace/app/terminal-logging-config.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/userspace/app/terminal-logging-config.ts)
- [packages/next/src/cli/internal/turbo-trace-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/turbo-trace-server.ts)
- [packages/next/src/telemetry/post-telemetry-payload.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/post-telemetry-payload.ts)
- [packages/next/src/trace/upload-trace.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/upload-trace.ts)
- [packages/next/src/telemetry/events/version.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/events/version.ts)
- [packages/next/src/server/patch-error-inspect.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/patch-error-inspect.ts)
- [packages/next/src/server/lib/app-info-log.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/app-info-log.ts)
- [packages/next/src/next-devtools/server/get-next-error-feedback-middleware.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/server/get-next-error-feedback-middleware.ts)
- [packages/next/src/cli/next-analyze.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-analyze.ts)
- [packages/next/src/telemetry/events/session-stopped.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/events/session-stopped.ts)
- [packages/next/src/server/lib/router-utils/instrumentation-globals.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/instrumentation-globals.external.ts)
</details>

## Overview

Next.js incorporates a unified telemetry and diagnostics subsystem designed to collect anonymous build and development usage metrics, track process memory performance, record garbage collection statistics, and persist structured build reports. This infrastructure enables the framework maintainers to prioritize feature development, track compatibility failures across platforms (such as SWC native bindings or glibc issues), and provide developers with granular diagnostics during builds and dev server lifecycles.
Sources: [packages/next/src/telemetry/storage.ts:51-83](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L51-L83)

The subsystem operates across several distinct operational boundaries: persistent local storage configurations managed via the `conf` package, detached background submission processes that prevent CLI hang on exit, V8 memory profiling triggers integrated with process signals (`SIGUSR2`), and trace log filters that upload selected performance spans to remote diagnostics endpoints. By decoupling event recording from synchronous network operations and gating collection behind environment variables (`NEXT_TELEMETRY_DISABLED`) or user opt-out preferences, the architecture balances comprehensive framework observability with strict user privacy guarantees.
Sources: [packages/next/src/telemetry/storage.ts:135-154](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L135-L154), [packages/next/src/trace/upload-trace.ts:4-58](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/upload-trace.ts#L4-L58)

```mermaid
flowchart TD
    A["CLI Command / Dev Server"] --> B{"Telemetry Enabled?"}
    B -- Yes --> C["Record Event / Span"]
    C --> D{"Ephemeral / CI / Dev?"}
    D -- Dev Mode --> E["Write to _events_<pid>.json"]
    E --> F["Spawn Detached Flush Process"]
    D -- Production / CI --> G["Submit Payload via postNextTelemetryPayload"]
    B -- No --> H["Drop Event"]
```
Sources: [packages/next/src/telemetry/storage.ts:219-253](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L219-L253)

---

## Telemetry Storage and Payload Pipeline

The core telemetry interface is encapsulated within the `Telemetry` class inside `packages/next/src/telemetry/storage.ts`. Upon initialization, it inspects the local execution environment to determine storage paths. Ephemeral environments such as Continuous Integration (CI) runners or Docker containers route telemetry metadata storage into the `.next/cache` directory, whereas standard environments utilize local configuration stores.
Sources: [packages/next/src/telemetry/storage.ts:41-49](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L41-L49)

Data privacy is enforced through a one-way SHA-256 hashing mechanism that prepends a randomly generated `salt` (16 hex bytes) before hashing project identifiers. The storage layer maintains an asynchronous event queue implemented as a `Setromise<RecordObject>>`. When events are recorded, they are tracked concurrently and can either be submitted synchronously via `postNextTelemetryPayload` with an automatic retry wrapper or flushed via detached background worker processes.
Sources: [packages/next/src/telemetry/storage.ts:113-173](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L113-L173)

```typescript
import { Telemetry } from 'next/dist/client/components/react-dev-overlay/../../telemetry/storage'

// Example initialization and recording of a custom telemetry event
const telemetry = new Telemetry({ distDir: process.cwd() })
await telemetry.record({
  eventName: 'NEXT_CUSTOM_EVENT',
  payload: { foo: 'bar' }
})
```
Sources: [packages/next/src/telemetry/storage.ts:62-82](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L62-L82), [packages/next/src/telemetry/storage.ts:174-217](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L174-L217)

---

## Detached Background Flushing Mechanism

To prevent CLI commands or development servers from blocking process termination while waiting for network I/O, the telemetry storage engine implements a detached flush mechanism (`flushDetached`). When a development session stops or a worker exits, unsubmitted events are serialized to a process-specific temporary file (`_events_id>.json`) inside the distribution directory.
Sources: [packages/next/src/telemetry/storage.ts:226-253](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L226-L253)

```mermaid
sequenceDiagram
    participant CLI as Main Process
    participant FS as File System
    participant Detached as detached-flush.ts

    CLI->>FS: Write unsubmitted events to _events_<pid>.json
    CLI->>Detached: Spawn detached process (mode, dir, eventsFile)
    Note over CLI: Main process exits immediately without blocking
    Detached->>FS: Read and parse _eventsFile
    Detached->>Telemetry: Instantiate Telemetry & record(events)
    Detached->>Telemetry: await telemetry.flush() & post payload
    Detached->>FS: fs.unlinkSync(eventsFile)
```
Sources: [packages/next/src/telemetry/detached-flush.ts:13-53](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/detached-flush.ts#L13-L53)

> [!WARNING]
> Detached flush worker processes rely on unique process IDs (`_events_id>.json`) to prevent race conditions between parent and child processes writing concurrently to the distribution directory.
Sources: [packages/next/src/telemetry/storage.ts:244-245](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/storage.ts#L244-L245)

---

## Build Diagnostics and Incremental Metrics

The diagnostics subsystem (`packages/next/src/diagnostics/build-diagnostics.ts`) manages persistent JSON artifacts written to the `.next/diagnostics/` directory during compilation and static generation. These files provide post-mortem debugging data when builds fail or performance degrades.
Sources: [packages/next/src/diagnostics/build-diagnostics.ts:7-27](https://github.com/blade47/next.js/blob/main/packages/next/src/diagnostics/build-diagnostics.ts#L7-L27)

| Diagnostic File Name | Target Interface | Description |
| :--- | :--- | :--- |
| `build-diagnostics.json` | `BuildDiagnostics` | Records active build stages and merged build configuration options. |
| `fetch-metrics.json` | `Record<string, FetchMetrics>` | Captures HTTP fetch metrics collected during static page generation per app path. |
| `incremental-build-diagnostics.json` | `IncrementalBuildDiagnostics` | Tracks changed/unchanged app paths, page paths, and Git SHAs during incremental builds. |
| `framework.json` | `{ name: string, version: string }` | Records the exact Next.js framework version used for the build. |

Sources: [packages/next/src/diagnostics/build-diagnostics.ts:13-96](https://github.com/blade47/next.js/blob/main/packages/next/src/diagnostics/build-diagnostics.ts#L13-L96)

```typescript
import { updateBuildDiagnostics } from 'next/dist/diagnostics/build-diagnostics'

// Updating current build stage prior to compilation steps
await updateBuildDiagnostics({
  buildStage: 'bundling-webpack',
  buildOptions: { target: 'server' }
})
```
Sources: [packages/next/src/diagnostics/build-diagnostics.ts:48-67](https://github.com/blade47/next.js/blob/main/packages/next/src/diagnostics/build-diagnostics.ts#L48-L67)

---

## Memory Tracing and Garbage Collection Monitoring

When memory debugging mode is activated via startup hooks (`packages/next/src/lib/memory/startup.ts`), Next.js hooks into Node.js V8 heap statistics and performance hooks to observe memory pressure and garbage collection overhead.
Sources: [packages/next/src/lib/memory/startup.ts:7-51](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/startup.ts#L7-51)

```mermaid
flowchart LR
    A["Process Startup"] --> B["Enable Memory Debugging"]
    B --> C["v8.setHeapSnapshotNearHeapLimit(1)"]
    B --> D["v8.setFlagsFromString('--detect-ineffective-gcs-near-heap-limit')"]
    B --> E["Start PerformanceObserver (gc)"]
    B --> F["Start Periodic Timer (20s)"]
    F --> G["Record RSS, HeapUsed, HeapMax"]
    G --> H{"Heap > 70% Limit?"}
    H -- Yes --> I["Generate .heapsnapshot file"]
```
Sources: [packages/next/src/lib/memory/startup.ts:11-32](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/startup.ts#L11-32), [packages/next/src/lib/memory/trace.ts:27-76](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/trace.ts#L27-L76)

The garbage collection observer (`packages/next/src/lib/memory/gc-observer.ts`) uses a `PerformanceObserver` listening for `gc` entry types. Any garbage collection cycle taking longer than `LONG_RUNNING_GC_THRESHOLD_MS` (15ms) triggers a warning log. Additionally, sending a `SIGUSR2` signal to the Node.js process forces an on-demand V8 heap snapshot export.
Sources: [packages/next/src/lib/memory/gc-observer.ts:5-27](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/gc-observer.ts#L5-L27), [packages/next/src/lib/memory/startup.ts:22-29](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/startup.ts#L22-29)

> [!IMPORTANT]
> Heap snapshots generated during high memory pressure will take significant time to complete and may temporarily freeze event loop execution; they are guarded by an `alreadyGeneratedHeapSnapshot` boolean flag to prevent cascading disk writes when heap utilization remains pegged above 70%.
Sources: [packages/next/src/lib/memory/trace.ts:8-9](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/trace.ts#L8-9), [packages/next/src/lib/memory/trace.ts:108-117](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/memory/trace.ts#L108-117)

---

## Trace Uploads and Filtering Architecture

Trace event collection and uploading are managed by `packages/next/src/trace/trace-uploader.ts` and `packages/next/src/trace/upload-trace.ts`. During development or build execution, trace spans are written to `.next/trace`. The uploader script reads the trace log line by line, filters events matching predefined access lists (`DEV_ALLOWED_EVENTS` or `BUILD_ALLOWED_EVENTS`), inherits parent feature flags, and posts structured payloads containing session metadata and filtered traces.
Sources: [packages/next/src/trace/trace-uploader.ts:115-225](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/trace-uploader.ts#L115-L225), [packages/next/src/trace/upload-trace.ts:4-58](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/upload-trace.ts#L4-L58)

| Access List Category | Included Trace Span Names |
| :--- | :--- |
| `COMMON_ALLOWED_EVENTS` | `memory-usage` |
| `DEV_ALLOWED_EVENTS` | `client-hmr-latency`, `render-path`, `hot-reloader`, `webpack-invalid-client`, `webpack-invalidated-server`, `navigation-to-hydration`, `start-dev-server`, `compile-path`, `server-restart-close-to-memory-threshold` |
| `BUILD_ALLOWED_EVENTS` | `next-build`, `run-turbopack`, `webpack-compilation`, `run-webpack-compiler`, `create-entrypoints`, `static-generation`, `next-export`, `run-typescript`, `run-eslint` |

Sources: [packages/next/src/trace/trace-uploader.ts:10-56](https://github.com/blade47/next.js/blob/main/packages/next/src/trace/trace-uploader.ts#L10-56)

---

## Model Context Protocol (MCP) Telemetry and Metadata Tools

Next.js embeds Model Context Protocol (MCP) servers and tracking infrastructure (`packages/next/src/server/mcp/mcp-telemetry-tracker.ts`) to record tool invocations during developer assistance workflows. Tool usages are accumulated in a private `Map<McpToolName, number>` and mapped into telemetry feature usage events upon session completion.
Sources: [packages/next/src/server/mcp/mcp-telemetry-tracker.ts:1-47](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/mcp-telemetry-tracker.ts#L1-47), [packages/next/src/server/mcp/mcp-telemetry-tracker.ts:69-83](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/mcp-telemetry-tracker.ts#L69-L83)

The `get_page_metadata` MCP tool (`packages/next/src/server/mcp/tools/get-page-metadata.ts`) queries active browser sessions via HMR communication channels, retrieves segment trie data, converts them into page metadata structures, and sorts them using a strict boundary precedence ordering:
Sources: [packages/next/src/server/mcp/tools/get-page-metadata.ts:19-117](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/tools/get-page-metadata.ts#L19-117)

1. Layout components (`type === 'layout'`)
2. Error or loading boundaries (`type.startsWith('boundary:')`)
3. Page components (`type === 'page'`)
4. Fallback default order (`3`)
Sources: [packages/next/src/server/mcp/tools/get-page-metadata.ts:194-206](https://github.com/blade47/next.js/blob/main/packages/next/src/server/mcp/tools/get-page-metadata.ts#L194-L206)

## Related

- [CLI Commands](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/build-and-config/cli-commands)


## Sitemap

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