Prompt and scope
A multilingual microservice platform uses OpenTracing APIs, vendor shims, and OpenTelemetry SDKs. Since March 2026, the OpenTelemetry specification no longer requires new implementations to provide OpenTracing compatibility, while existing shims remain needed during transition. Design a migration that preserves traces, controls cost, and allows a single service to roll back.
What the interviewer is testing
The interviewer is testing whether you separate API, data-semantic, and backend-protocol compatibility; handle trace and span attribute mapping, context propagation, sampling consistency, dual-write cost, and vendor lock-in. A strong answer gives migration order, acceptance metrics, and failure isolation instead of only replacing dependencies.
Questions to clarify first
- Which languages and frameworks use OpenTracing, and have shims changed its semantics?
- Does the backend accept OTLP, and must historical data and query dimensions remain stable?
- Is the priority zero loss, low overhead, unified semantics, or vendor replaceability?
- Is temporary dual writing allowed, and what are the sampling and per-service cost limits?
30-second answer
“I would split the migration into API, semantics, transport, and operations. First freeze new OpenTracing dependencies and inventory shims, propagation formats, and key attributes. In one service, add native OpenTelemetry while retaining the shim as a compatibility entry point, then compare them with one context and sampling decision. After trace continuity, error rate, attribute coverage, latency, and cost meet gates, expand by language and dependency topology. A failure rolls back one service’s entry or export route, not the shared Collector platform.”
Step-by-step solution
1. Inventory calls and semantics
Create a service, language, OpenTracing package, shim version, propagation-format, and export-path inventory. Mark custom tags, logs, baggage, and span names, then map each to OpenTelemetry attributes, events, links, and baggage. Start with stateless services whose boundaries are clear, not the most customized tracer.
2. Define the compatibility boundary
Move application code toward native OpenTelemetry tracers. Keep a shim for libraries that cannot yet change, but freeze new shim features. Context propagation must remain consistent at ingress, asynchronous queues, RPC, and batch boundaries; similar API names do not prove equivalent sampling or parent relationships.
3. Place controlled dual writing
Prefer controlled routing at the SDK or Collector export boundary instead of generating two span sets in business code. If dual writing is required, set per-service sampling caps, queue limits, retries, and drop metrics, distinguishing “business span not created” from “export failed.” Give the dual-write window an explicit exit condition.
4. Keep the backend queryable
Freeze names for service, operation, status, and critical business attributes during migration. Send the same request set through old and new paths and compare trace counts, parent-child relationships, error status, latency percentiles, and exemplars. If backend query semantics change, provide an adapter or two dashboard versions before changing the default view.
5. Canary with cost guardrails
Migrate in batches by language, team, or dependency tree. Track end-to-end trace continuity, span loss, Collector queues, CPU and memory, egress, and cost per million spans. When a threshold fails, stop admitting new services while preserving already migrated services and raw evidence.
6. Roll back with lifecycle controls
Keep a tracer initialization switch, dependency version, and configuration snapshot for each service. Roll back by switching that service’s entry or export route, rather than deleting shared Collector resources. Before removing a shim, verify that no downstream library still obtains context through a global tracer, and retain compatibility monitoring for a defined window.
Model answer
I would freeze new OpenTracing compatibility work and inventory calls, semantics, propagation, and exports. Native OpenTelemetry APIs move service by service; unmodifiable libraries continue through shims, with Context, sampling, and attribute mappings fixed by contract tests. Dual writing is limited at the SDK or export boundary, with metrics for continuity, attribute coverage, Collector queues, latency, and cost. Canary by language and dependency topology. On failure, disable one service’s new route and restore its old export while retaining configuration, events, and comparison data; remove shims only after all services are stable.
Common mistakes
- Only replacing imports → parent, baggage, or attribute semantics change → test propagation and semantic contracts.
- Dual writing in every business call → span volume and cost explode → centralize and cap routing at the SDK or export boundary.
- Watching only Collector success → the application already lost spans → separate creation, queueing, export, and backend metrics.
- Migrating every service at once → the blast radius is too large → canary by language and dependency topology.
- Deleting shims immediately → an unmodified library fails to start → freeze new dependencies and verify references are gone.
Follow-up questions and responses
Why not require every team to switch at once?
Shared libraries, release schedules, and language SDKs differ, so a synchronized cutover creates a large blast radius. Layered compatibility keeps services running while native APIs become the center of new work.
How do you prove that traces were not lost?
Inject a stable identifier into repeatable requests, compare ingress, service-to-service propagation, Collector receipt, and backend query counts, then sample-check parent links, status, and key attributes.
Can dual writing change sampling?
Yes. Independently sampling two tracers can break a trace or double cost. Decide sampling in the shared context and make both routes inherit that decision.
When can the compatibility layer be removed?
After dependency scans find no OpenTracing entry points, contract tests cover propagation and semantics, canary metrics meet their gates, and no rollback occurs during the retention window. Then remove the shim and retain an audit record.