Build1 publisher2 min readPublished
Next.js 16's stable instrumentation.ts closes first-request telemetry gaps, though slow initialization can still delay app boot
Next.js 16's stable instrumentation.ts runs telemetry setup once per runtime before app code loads, a dev.to walkthrough says. Because an async register holds the server until it resolves, a three-second SDK connect becomes three seconds of cold start.
The Engineer · Build desk

What happened
- Next.js 16 marks instrumentation.ts stable, and its register function runs once per runtime environment before middleware, route handlers or React components load, per a dev.to walkthrough.
- When register is async, Next.js waits for its promise to resolve before starting the HTTP server or invoking middleware.
- The article's OpenTelemetry example checks that NEXT_RUNTIME is nodejs, then dynamically imports @vercel/otel/register inside register.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- cost SDK setup latency moves onto the boot path, and serverless apps pay it at every cold start, the case the article links to P99 latency.
- constraint Teams that drop their init wrappers still maintain a NEXT_RUNTIME branch, because register is also invoked outside Node.js and Node-only setup has to be guarded.
- decision Where Sentry and OpenTelemetry get initialized is now a real choice: SDK imports left in _app.tsx or middleware keep the first-request race the article describes.
The wrappers exist because of an ordering bug. According to the dev.to walkthrough, teams that import Sentry or OpenTelemetry from _app.tsx or middleware get silent production failures, because the SDK has not initialized when the first request lands [1]. The usual patch is a custom wrapper plus a comment telling everyone to import it first. The article says a dedicated entry point retires both [14]. I think the framework is the right place for that guarantee. A comment cannot enforce import order, and a hook that runs before middleware and route handlers can [2]. The article says Next.js finds the file at the project root or under src/, with no flag or experimental toggle to set [10].
The ordering is enforced by blocking. Next.js holds the HTTP server and middleware until an async register resolves [4], so init time becomes boot time. The article's three-second Sentry figure is an illustration [5]. For it to hold on a real deployment, the SDK's init has to await its ingest connection inside register. An init that returns before connecting keeps that time off the boot path. I'd accept the blocking on a long-running Node.js server, where register runs once at process start [3]. On serverless it runs on every cold start [3], and the article ties cold starts to P99 latency [5].
Deleting the wrapper leaves a small one behind. The article's OpenTelemetry example gates its import on process.env.NEXT_RUNTIME being "nodejs" [6]. Register runs once per runtime environment [2], so the guard only makes sense if more than one runtime calls it [13]. The article says register code has full access to the filesystem, environment variables and network [8]. Given the guard, that statement describes the Node.js branch. Anything in a Sentry or OpenTelemetry setup that needs Node.js APIs has to sit inside that check.
The prose and the code also disagree about the package. The article describes @vercel/otel as a zero-config OpenTelemetry package that Vercel maintains [12], and says it exports a registerOTel function designed for this file [7]. The snippet never calls registerOTel. It dynamically imports an @vercel/otel/register subpath instead [6].
All of this rests on one post, and it discloses that it was written with AI assistance under human supervision and review [9]. It does not link Next.js release notes, show its Sentry initialization code, or include a trace from a running app. The claims that @vercel/otel adds propagation headers to outbound fetch calls and nests Prisma or Drizzle queries as child spans come from the article's own description of the package [11].
What to watch
- Next.js documentation confirming instrumentation.ts is stable in version 16 and listing which runtimes call register.
- Whether @vercel/otel documents an @vercel/otel/register subpath import or only the registerOTel function.
- Measured cold-start times for Sentry or OpenTelemetry init inside an async register on a serverless host.