~3 min read • Updated Dec 11, 2025
Why Observability Matters
As applications grow more complex, diagnosing performance issues becomes harder. Observability tools like logging and metrics help developers understand app behavior, detect problems early, and improve user experience.
Using OpenTelemetry
OpenTelemetry is a platform-agnostic standard for observability. Next.js supports OpenTelemetry out of the box, and you can use it to instrument your app without locking into a specific provider.
Quick Setup with @vercel/otel
Install the required packages:
npm install @vercel/otel @opentelemetry/sdk-logs @opentelemetry/api-logs @opentelemetry/instrumentationCreate an instrumentation.ts file in your project root:
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel({ serviceName: 'next-app' })
}Manual Configuration
If you need more control, configure OpenTelemetry manually:
npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-httpUse conditional imports for Node runtime:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation.node.ts')
}
}Then configure the SDK:
// instrumentation.node.ts
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { resourceFromAttributes } from '@opentelemetry/resources'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'next-app',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()Testing Your Instrumentation
Use an OpenTelemetry Collector or dev environment to test traces. Set NEXT_OTEL_VERBOSE=1 to see more spans.
Deployment
- On Vercel: OpenTelemetry works out of the box
- Self-hosted: Set up your own OpenTelemetry Collector
Custom Exporters
You can use custom exporters with either @vercel/otel or manual setup.
Creating Custom Spans
Install the API package:
npm install @opentelemetry/apiExample span for fetching GitHub stars:
import { trace } from '@opentelemetry/api'
export async function fetchGithubStars() {
return await trace
.getTracer('nextjs-example')
.startActiveSpan('fetchGithubStars', async (span) => {
try {
return await getValue()
} finally {
span.end()
}
})
}Default Spans in Next.js
Next.js automatically generates spans for:
- BaseServer.handleRequest: Root span for incoming requests
- AppRender.getBodyResult: Rendering routes in App Router
- AppRender.fetch: Fetch requests
- AppRouteRouteHandlers.runHandler: API route execution
- Render.getServerSideProps: SSR data fetching
- Render.getStaticProps: Static data fetching
- Render.renderDocument: Pages Router rendering
- ResolveMetadata.generateMetadata: Metadata generation
- NextNodeServer.findPageComponents: Resolving page components
- NextNodeServer.getLayoutOrPageModule: Loading layout/page modules
- NextNodeServer.startResponse: Sending first byte of response
Conclusion
OpenTelemetry gives you powerful visibility into your Next.js app. Whether you use @vercel/otel or configure it manually, instrumentation helps you detect issues early, optimize performance, and deliver a better experience to your users.
Written & researched by Dr. Shahin Siami