deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

Next.js 16 stabilizes instrumentation.ts for wrapper-free OpenTelemetry and Sentry wiring

Next.js 16 promotes instrumentation.ts to a stable, guaranteed init hook that runs before middleware, routes and components, letting teams set up OpenTelemetry and Sentry without custom wrappers.

Next.js 16 stabilizes instrumentation.ts for wrapper-free OpenTelemetry and Sentry wiring

A guaranteed entry point for observability

Most observability headaches in Next.js come down to initialization timing. According to a dev.to article published on the platform, teams that import Sentry or an OpenTelemetry collector inside _app.tsx or middleware can end up with an SDK that never finished initializing before the first request arrived, and the resulting telemetry gaps surface exactly when production needs visibility.

Next.js 16 responds by marking instrumentation.ts stable. The file exports a single register function that the framework calls exactly once per runtime environment, before middleware, route handlers, or React components load. The dev.to post frames the shift as turning observability from a runtime concern into a build-time contract: instead of wrapper functions and "import this first" comments, the framework itself provides a deterministic boot sequence.

What register actually guarantees

The execution model matters as much as the stability label:

  • In serverless deployments, register runs once per cold start; on long-lived Node.js servers it runs once at process boot. It is not a per-request hook.
  • It does not execute inside React Server Component scope and does not share middleware's execution context.
  • It runs in a Node.js context with access to the filesystem, environment variables, and network I/O, which is what SDK initialization typically needs.
  • The function may be synchronous or asynchronous. If async, Next.js waits for the promise to resolve before starting the HTTP server or invoking middleware.

The file lives at the root of src/ or alongside next.config.js at the project root, and the framework discovers it automatically — no configuration flags or experimental toggles.

That awaited boot has a cost the article is candid about: slow initialization blocks the entire startup sequence. An SDK that takes three seconds to reach its ingest endpoint adds three seconds to cold start time, so teams on serverless platforms, where cold starts feed directly into P99 latency, need to balance thorough setup against startup speed.

OpenTelemetry via @vercel/otel

For distributed tracing, the article points to @vercel/otel, Vercel's zero-config OpenTelemetry package. Its registration path is designed for instrumentation.ts:

ts export async function register() { if (process.env.NEXT_RUNTIME === "nodejs") { await import("@vercel/otel/register"); } }

With those few lines, the package auto-instruments HTTP, fetch, database, and framework boundaries — route handlers, middleware, Server Components, and API routes each get spans, outbound fetch calls carry trace context propagation headers, and database queries through libraries like Prisma or Drizzle appear as child spans under the active request trace. The NEXT_RUNTIME guard keeps Node-only SDK code out of the Edge Runtime, and the dynamic import avoids loading the SDK where it is not needed.

For data auto-instrumentation cannot infer, the standard OpenTelemetry API works directly. The article demonstrates an API route that starts a validate-payment span via trace.getTracer, sets attributes such as order amount and currency, records exceptions, sets an OK or ERROR status, and ends the span in a finally block — putting business-specific fields onto the trace timeline where observability platforms can query them.

Sentry without config sprawl

Sentry's traditional Next.js setup required separate sentry.client.config.ts and sentry.server.config.ts files imported at the top of _app.tsx and route files, a pattern the article describes as fragmented and timing-sensitive. With instrumentation.ts, a single Sentry.init call inside register covers initialization, with branching on NEXT_RUNTIME to configure Node.js and Edge environments differently. Integrations such as HTTP tracing and Prisma instrumentation can be attached in the same place, and the article notes that error-boundary behavior with React Server Components works out of the box because the SDK is live before the first component renders.

Why it matters

Stable instrumentation.ts removes an entire class of silent failure from Next.js deployments: the race between framework code and observability SDKs. Teams get one well-defined place to initialize tracing, error tracking, and logging pipelines, with an execution order the framework guarantees rather than one developers approximate with import ordering. The tradeoff is explicit — initialization now sits on the boot critical path — but that visibility is preferable to telemetry that quietly never started. For anyone running Next.js in production with Sentry, Datadog, or OpenTelemetry backends, this is the hook to migrate init logic into.

  • #next-js
  • #opentelemetry
  • #sentry
  • #observability
  • #javascript

Related posts