
OpenTelemetry JavaScript SDK 3.0 shipped on October 15. It is a housekeeping release — but “housekeeping” here means four breaking changes that will silently break your Node.js apps the moment you run npm update without reading the changelog. The headlines: three trace packages are gone, Jaeger support is dropped, Node.js 18 and 20 no longer work, and re-exports you probably depended on are removed. Here is exactly what changed and the fastest path to fix it.
Check Node.js First — That’s the Hard Gate
Before touching a single dependency, run node --version. If you are on anything below v22, SDK 3.0 will not run. Node.js 22 LTS is the minimum. Node.js 18 hit end-of-life in April 2026. Node.js 20 hit EOL the same month. The OTel team has been clear about this for months, but teams in enterprise environments tend to lag. Upgrading to Node.js 22 is the non-optional first step — and it is worth doing regardless of this migration, given Node 18 has received no security patches for six months.
The Biggest Change: Three Trace Packages Became One
The most widespread breaking change is the consolidation of the trace SDK. @opentelemetry/sdk-trace-node, @opentelemetry/sdk-trace-base, and @opentelemetry/sdk-trace-web are all gone. They merged into a single @opentelemetry/sdk-trace package. Nearly every OTel-instrumented application imports at least one of these three. The good news: the unified package was available as a backport since June 2026 (v2.9.0), so you can migrate today without jumping to 3.0. Track the full migration details in GitHub issue #6926.
The import change is mechanical:
// Before
import { NodeTracerProvider } from @opentelemetry/sdk-trace-node;
import { SimpleSpanProcessor } from @opentelemetry/sdk-trace-base;
// After
import { NodeTracerProvider, SimpleSpanProcessor } from @opentelemetry/sdk-trace;
The consolidation also removes the .register() method from NodeTracerProvider and WebTracerProvider. That method never existed in the logs or metrics SDKs — it was a trace-specific convenience that created API inconsistency. The replacement is explicit:
// Before
provider.register({ propagator: new W3CTraceContextPropagator() });
// After
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
api.trace.setGlobalTracerProvider(provider);
api.propagation.setGlobalPropagator(new W3CTraceContextPropagator());
More verbose, but consistent with how you initialize every other OTel SDK component.
Jaeger Support Is Gone — Switch to OTLP
Four packages are dropped outright: @opentelemetry/propagator-jaeger, @opentelemetry/exporter-jaeger, @opentelemetry/shim-opentracing, and @opentelemetry/shim-opencensus. If you are still using the Jaeger exporter, the fix is to switch to the OTLP exporter and point it at your Jaeger backend — Jaeger has accepted OTLP natively since v1.35, so you likely do not need to touch your Jaeger infrastructure at all.
// Before
import { JaegerExporter } from @opentelemetry/exporter-jaeger;
const exporter = new JaegerExporter({ endpoint: http://jaeger:14268/api/traces });
// After
import { OTLPTraceExporter } from @opentelemetry/exporter-trace-otlp-http;
const exporter = new OTLPTraceExporter({ url: http://jaeger:4318/v1/traces });
Port 4318 is Jaeger’s OTLP HTTP receiver. For gRPC, use port 4317 with @opentelemetry/exporter-trace-otlp-grpc. If you are on OpenTracing or OpenCensus shims, there is no equivalent drop-in — those legacy APIs need migration to native OpenTelemetry instrumentation. The shims existed to ease transition, not to be permanent infrastructure.
Re-exports Are Gone — Imports Need to Be Explicit
@opentelemetry/sdk-node was quietly re-exporting api, core, sdk-logs, sdk-metrics, and resources. That convenience is removed. If your codebase imported these through sdk-node, add the direct imports:
// Before (worked as an accidental re-export)
import { Resource } from @opentelemetry/sdk-node;
// After
import { Resource } from @opentelemetry/resources;
A related change: deep path imports into build output now throw ERR_PACKAGE_PATH_NOT_EXPORTED. Anything that looks like @opentelemetry/sdk-logs/build/src/Logger will fail. SDK 3.0 ships a proper exports map — use the top-level package import instead.
ESM/CJS: Mostly Transparent, One Caveat
SDK 3.0 ships proper dual ESM/CJS exports via a build migration to tsdown. Files moved from build/src/ to dist/ with .cjs/.mjs extensions. For most teams, bundlers that respect package.json exports handle this automatically. The only teams affected are those with custom webpack or rollup configurations that hardcoded paths into OTel package internals — those paths no longer exist. The upside: ESM applications no longer lose spans due to missing loader hooks, which was a real pain in SDK 2.x.
Your Migration Checklist
Run these five checks before upgrading. Most can be done with a codebase search:
- Node.js version:
node --versionmust return v22 or higher - Trace package imports: Search for
sdk-trace-node,sdk-trace-base,sdk-trace-web— replace all withsdk-trace - Jaeger packages: Search for
propagator-jaeger,exporter-jaeger— switch to OTLP exporter - Legacy shims: Search for
shim-opentracing,shim-opencensus— these require native OTel migration, no replacement shim exists - sdk-node re-exports: Search imports from
@opentelemetry/sdk-nodefor symbols likeResource,metrics,logs— add direct package imports
Should You Upgrade Now?
If you are on Node.js 22 and not using Jaeger or the legacy shims, the migration is a few import path changes — probably an hour of work for most codebases. The sdk-trace unified package has been available since June so you can stage the trace migration separately from the 3.0 upgrade.
If you are on Node.js 18 or 20, fix that first. Running a six-month-old EOL runtime to avoid an upgrade is not a maintenance strategy. The 2.x branch is in feature-freeze since September 1 — critical security fixes only. The migration cost is low for most teams. The cost of sitting on an EOL runtime and a security-frozen SDK compounds quietly until it does not.













