OpenTelemetry for Node.js — the wiring that actually works in production
May 28, 2026 · 1 min read · by Sudhanshu K.
OpenTelemetry has effectively won the distributed-tracing argument. Datadog, Honeycomb, Grafana Tempo, AWS X-Ray, Azure Monitor — all of them ingest OTLP directly, which means instrumenting your service with OpenTelemetry once gives you portability across vendors and tooling.
The standard wiring for a Node.js service is well-documented but full of small landmines. Here's the setup that works in production, including the auto-instrumentation we enable and the noisy ones we explicitly disable.
Wiring at process start
// otel.js — imported first via `node --import ./otel.js app.js`
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
new NodeSDK({
serviceName: process.env.OTEL_SERVICE_NAME,
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
}),
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': { enabled: false }, // too noisy
'@opentelemetry/instrumentation-net': { enabled: false }, // too noisy
}),
],
}).start();The --import flag is critical — OpenTelemetry must load before your app code so it can monkey-patch the right modules.
The full write-up covers:
- Why auto-instrumentation is the right starting point (don't hand-instrument every span)
- Sampling: head sampling, tail sampling, and the latency-vs-budget trade-off
- Context propagation through
async_hooksand the rare places it leaks - Resource attributes that make traces searchable (k8s pod, deploy version, region)
- The collector pattern (one sidecar per host, batched export)
- Exporters by vendor — Datadog OTLP, Honeycomb, Grafana Tempo
We ship this wiring as part of every managed Node.js engagement.
Full article available
Read the full article