Next.js tracing installation
- 1
Install OpenTelemetry packages
RequiredFor the complete SDK reference, see the OpenTelemetry JavaScript docs.
Terminal@opentelemetry/exporter-trace-otlp-protois the OTLP HTTP/protobuf trace exporter. The similarly named-otlp-httppackage sends HTTP/JSON and-otlp-grpcsends gRPC, so pick-prototo match this guide. - 2
Get your project token
RequiredYou'll need your PostHog project token to authenticate trace requests. This is the same token you use for capturing events with the PostHog SDK.
Important: Use your project token which starts with
phc_. Do not use a personal API key (which starts withphx_).You can find your project token in Project settings.
- 3
Enable instrumentation in Next.js
RequiredNote: This step is only needed on Next.js 13.2–14.x. For Next.js 15 and later,
instrumentation.tsis enabled by default and theexperimental.instrumentationHookoption is deprecated — remove it from your config if it's set.On Next.js 14 and earlier, add the following to your
next.config.js(ornext.config.mjs) to enable the instrumentation hook:JavaScript - 4
Create the instrumentation file
RequiredCreate an
instrumentation.ts(orinstrumentation.js) file in the root of your project (or insidesrc/if you use that folder).typescriptNote: The
tracerProvideris created outside ofregister()so it can be exported and used to flush spans in route handlers. This pattern is necessary because Route Handlers complete execution before batched spans have a chance to be sent to the collector. By exporting the provider, we can manually flush spans at the end of each request.Note:
@opentelemetry/sdk-trace-nodeonly works in the Node.js runtime. If parts of your app use the edge runtime (e.g. middleware), the Next.js OpenTelemetry guide recommends moving Node-only setup into a separate file thatregister()dynamically imports behind theNEXT_RUNTIME === 'nodejs'check.Alternatively, you can pass the token as a query parameter:
typescript - 5
Create spans
RequiredWrap the operations you want to measure in spans, and attach attributes for context. Then flush the provider before the serverless function freezes.
typescriptImportant: Without calling
forceFlush(), your spans may not be sent. When deploying to a serverless platform like Vercel, Route Handlers complete execution before the OpenTelemetry batch processor has a chance to export spans, and the function freezes before the batch is flushed. Theafter()function fromnext/serverruns code after the response is sent, ensuring spans are flushed before the serverless function freezes.Note:
after()is stable in Next.js 15.1+ (available asunstable_afterin 15.0). On Next.js 14 and earlier, it doesn't exist — flush before returning instead:typescript - 6
Next steps
CheckpointWhat you can do with your tracesAction Description Why you need distributed tracing What a trace shows you that nothing else does Explore traces Read a trace as a waterfall to see where time goes Filter spans Narrow down by service, status, duration, and attributes Propagate context Pass trace context across services so spans join the same trace