skip to content

Your services are instrumented with the OpenTelemetry SDKs and the telemetry has to reach an observability backend. Make the case for exporting in OTLP (the OpenTelemetry Protocol) rather than using a backend-specific exporter inside the process, say when a native exporter is still the right call, and explain how you would choose between OTLP's gRPC and HTTP transports.

level: middleimportance: must knowfreq 55%

answer

  1. one protocol, three signals, present in every SDK
  2. translate outside the process — collector or vendor edge
  3. native exporter = destination becomes a redeploy
  4. native exporters deprecated once backends ingested OTLP
  5. gRPC in-cluster; HTTP through proxies, meshes, browsers

basics

~20 s

OTLP is the one exporter every OpenTelemetry SDK ships and it carries traces, metrics and logs, so the destination stays a config change. A native exporter compiles a vendor's protocol into the process, making a backend switch a redeploy. Use gRPC in-cluster, HTTP where proxies or browsers break it.

solid answer

~50 s

OTLP is OpenTelemetry's own protocol, defined for all three signals, and the only exporter guaranteed to be present in every SDK. Exporting OTLP means the application holds no opinion about the destination: point it at a collector or a vendor's OTLP ingest and swapping, dual-shipping or adding a backend is a routing decision made outside the process. A backend-native exporter does the reverse — it links a vendor's protocol and its release cadence into your build, so changing destination becomes a rebuild and a redeploy of every service. Several native exporters were deprecated and removed from the SDKs once the backends themselves learned to ingest OTLP. Native exporters still earn their place where the interaction model differs (a pull-based scrape endpoint), where the backend genuinely has no OTLP ingest, or where you cannot run a collector at all. Transport: **gRPC** rides HTTP/2 with long-lived connections and per-export status; **HTTP** works anywhere HTTP/1.1 does. Choose HTTP when proxies, L4 load balancers, meshes, gateways or browser/edge runtimes make gRPC awkward.

code

text · 10 lines
text
native exporter
  [service A]--vendorProto-->[vendor X]
  [service B]--vendorProto-->[vendor X]
  switch vendor => change code in A and B, rebuild, redeploy

OTLP
  [service A]--OTLP-->\
                       [collector]--(any protocol)-->[vendor X | vendor Y | archive]
  [service B]--OTLP-->/
  switch vendor => edit collector pipeline; services untouched

go deeper

for a junior

Know that OTLP is OpenTelemetry's own protocol, that every SDK can speak it, and that using it means the application does not contain backend-specific code.

for a middle

Explain the decoupling argument concretely — destination becomes configuration rather than a redeploy — note that native exporters were removed once backends ingested OTLP, and pick between gRPC and HTTP on infrastructure compatibility.

for a senior

Add the operational detail: where translation and policy belong (a collector), the HTTP/2 connection-stickiness problem in front of a collector fleet, and the honest cases where a native exporter is still right.

for a principal

Frame it as a coupling and portability decision for the whole estate: instrumentation outlives vendors, translation is centralised so backend choice stays reversible, and the transport call is made per network path rather than as a single global standard.

## What the choice actually is An instrumented process has to serialise its telemetry and push it somewhere. Two families of exporter exist inside the SDKs. **OTLP** is OpenTelemetry's own protocol — one protobuf-defined schema covering traces, metrics and logs, with a gRPC binding and an HTTP binding. A **backend-native exporter** speaks some other system's ingest protocol directly from your process. The interesting part of the decision is not efficiency. It is *where the coupling to a destination lives*. ## Why OTLP is the default **It is the exporter that is always there.** Every OpenTelemetry SDK implements OTLP; native exporters exist unevenly across languages, so a polyglot estate that standardises on a native exporter standardises on something that some of its services cannot do. OTLP is also the only exporter that covers all three signals with one schema and one configuration surface, so traces, metrics and logs leave the process the same way instead of through three unrelated clients. **It keeps the destination outside the binary.** An application emitting OTLP knows only that there is an endpoint. Whether the other end is a sidecar collector, a gateway collector fleet or a vendor's own OTLP ingest is a deployment fact. That is what makes the following cheap: switching backends, running two backends side by side during an evaluation, routing one team's data elsewhere, inserting redaction or tail sampling in the middle. With a native exporter each of those is a code change propagated through every service and released on your slowest team's schedule. **It moves the N×M problem to one place.** Maintaining exporters for N backends across M languages is unsustainable; maintaining N exporters in the collector is tractable. That is precisely how the ecosystem resolved it: the collector owns translation, and the SDKs converged on OTLP. The consequence you should be able to state in an interview is the rule — *applications emit OTLP; translation to anything else happens outside the application.* **The direction of travel confirms it.** Backends added OTLP ingest, which made the corresponding in-SDK exporter redundant; dedicated Jaeger exporters were deprecated and then removed from the SDKs after Jaeger itself began accepting OTLP. Committing new code to a native exporter is therefore committing to a shrinking surface. ## When a native exporter is still correct Be able to name the exceptions, or the argument sounds dogmatic. - **A different interaction model.** A pull-based scrape endpoint is not a serialisation choice, it is an inversion of who initiates; that is a separate design decision rather than a competitor to OTLP push. - **No OTLP ingest at the destination and no collector allowed.** Some constrained or regulated deployments cannot run an extra process or sidecar; then the process must speak the destination's protocol itself. - **Something the vendor exposes that OTLP does not model.** If a proprietary feature depends on fields with no OTLP representation, translation cannot invent them. Check whether it is genuinely unrepresentable or merely conventional attributes. Even then, prefer OTLP out of the process and a translating hop, if you can have one. ## Choosing the transport Both OTLP bindings carry the same payload; the difference is entirely operational. **gRPC** (default port 4317) runs over HTTP/2: one long-lived connection, multiplexed streams, header compression, and a clear per-export status the exporter uses to decide retry versus drop. It is the sensible in-cluster default. Two operational wrinkles: an HTTP/2 connection is sticky, so an L4 load balancer in front of a collector fleet pins each client to one replica until it reconnects — you want an L7 proxy that balances requests, or a bounded maximum connection age on the receiver; and some corporate proxies, API gateways and older meshes mishandle or forbid h2c. **HTTP** (default port 4318) works wherever ordinary HTTP does, which is nearly everywhere: through egress proxies, TLS-terminating gateways, and CDNs. Retry decisions come from status codes, with 429 and 503 the retryable cases. Its body is normally the same binary protobuf; a JSON encoding also exists for environments where protobuf is impractical, at a significant size penalty. Browser and some edge runtimes cannot originate gRPC at all, so HTTP is the only option there. HTTP is also trivially inspectable when you are debugging an ingest problem. The endpoint and protocol environment variables that express this are the SDK-configuration topic; the decision itself is what this question is about. ## Interview framing Lead with coupling — emit OTLP, translate outside the process — then the concrete consequence (destination becomes config, not a redeploy), then the honest exceptions, then the gRPC/HTTP call framed as infrastructure compatibility rather than raw throughput.

  • If OTLP decouples the application from the backend, why bother running a collector when the vendor exposes its own OTLP ingest endpoint?
    Sending OTLP straight to the vendor is legitimate and is the simplest topology. A collector buys you things the SDK cannot: one place to fan out or dual-ship during a migration, redaction and attribute rewriting before data leaves your network, tail-based sampling that needs a whole trace, batching and retry that survive an application restart, and an egress point where credentials live instead of in every service. Without one you still avoid vendor code in the process, but every routing or policy change becomes a fleet-wide config rollout.
  • A team wants to keep a vendor-native exporter because it is 'more efficient than OTLP'. How do you evaluate that claim?
    Ask for the measurement and what it is measuring. Serialisation and transport costs of OTLP are small relative to the cost of producing the telemetry, and the usual efficiency levers — batching, compression, sampling — are available on both paths. If a real difference exists it is normally an artefact of different default batch sizes or compression settings rather than the protocol. Weigh any residual difference against the operational cost you are buying: a destination that can only be changed by rebuilding and redeploying every service.
  • You standardised on OTLP/gRPC to a collector fleet behind a load balancer and one collector replica is receiving most of the traffic. What is happening?
    gRPC runs over HTTP/2, so a client opens one long-lived connection and reuses it. An L4 load balancer balances connections, not requests, so each client stays pinned to whichever replica it first reached, and replicas added later get nothing. Fix it with an L7 proxy that balances individual requests, a bounded maximum connection age on the receiver so clients periodically re-resolve and rebalance, or client-side load balancing. Switching that hop to OTLP/HTTP also sidesteps it.

A native exporter is like hard-wiring an appliance directly to a specific utility; OTLP is a standard plug. The adapter that matches the local socket lives outside the appliance, so moving house is a cable change, not rewiring the appliance.

saying these in an interview costs you the question

  • Claiming OTLP is chosen because it is faster or smaller on the wire — the argument is decoupling, not efficiency.
  • Believing OTLP and gRPC are the same thing, or that OTLP requires gRPC; OTLP has an HTTP binding that is a first-class option.
  • Asserting that native exporters no longer exist or are always wrong, with no account of pull-based destinations or deployments where no collector may run.
  • Thinking gRPC versus HTTP changes what is exported; they carry the same payload and differ operationally.
  • Assuming a backend that says it 'supports OTLP' supports all three signals equally.

context