What Is the Load Balancing Exporter in OpenTelemetry?

What Is the Load Balancing Exporter in OpenTelemetry?

The load balancing exporter is a component of the OpenTelemetry Collector that sends telemetry to a group of backend collectors and makes sure related data always lands on the same one. This guide explains why that matters, how it works, and how to run it safely.

Imagine a large post office that sorts letters for a whole city. Hundreds of clerks sit at the front counter, and behind them a row of sorting rooms each handle one group of streets. If a clerk simply threw each letter into any open room, letters for the same family could end up in five different rooms, and nobody could ever put them together. A smarter clerk looks at the address on each letter and always sends letters for the same street to the same room. The load balancing exporter does exactly this job for telemetry: it reads a small piece of identifying information on each piece of data and sends all related pieces to the same destination.

1Why Telemetry Needs Careful Routing

Before we meet the exporter, we need to understand the problem it exists to solve.

A quick picture of the OpenTelemetry Collector

The OpenTelemetry Collector is a program that receives telemetry data, which means traces, metrics and logs, then processes it and sends it onwards. It has three kinds of building blocks. Receivers accept data from applications. Processors change or filter the data on its way through. Exporters send the data to its next destination, which might be a storage system, a vendor service, or another collector. These pieces are joined together in pipelines, and one collector can run several pipelines at once.

In a small system a single collector is enough. As the system grows, one collector can no longer cope, so teams run many collectors side by side. At that point a new question appears: when an application or an upstream collector sends data to this group, which member of the group should receive each piece?

When any destination will do, and when it will not

For many jobs the answer is easy. If a collector only needs to compress data and forward it, any member of the group can do the work, and you can spread the load evenly with an ordinary load balancer. This is called stateless work, because each piece of data is handled alone and nothing needs to be remembered between pieces.

Other jobs are stateful. A tail-sampling processor, for example, must see all the spans of a trace before it decides whether to keep that trace. A component that turns spans into metrics must see all the related spans together to produce correct numbers. A component that combines cumulative metrics needs all the points of one series. For these jobs, scattering related data across different collectors breaks the result.

Simple Analogy

Think of a jigsaw puzzle split among several tables. If every table receives a random handful of pieces, no table can finish any part of the picture. If each table receives all the pieces of one corner, every table can complete its corner. Routing by a shared key is how you hand out the corners.

Stateless
Any collector can handle any piece
Stateful
Related pieces must meet in one place
Router
The exporter makes sure they do

How collectors are usually arranged

Teams arrange collectors in a few common shapes. In the agent shape, a small collector runs on every machine or beside every group of applications. It collects data locally, adds useful labels such as the machine name, and forwards onwards. Agents are cheap, numerous and mostly stateless. In the gateway shape, a smaller group of larger collectors receives data from many agents or applications, performs heavier processing, and sends the result to storage. Gateways are fewer, and some of them hold state.

As traffic increases, the gateway shape often needs to be split into two layers, because the stateless parts of the work and the stateful parts of the work scale in different ways. Stateless work grows by adding more identical members behind an ordinary balancer. Stateful work grows only if each member owns a clear share of the data. The load balancing exporter is the device that hands out those shares, and it is the reason a two-layer gateway can work at all.

ShapeWhere it runsTypical workHolds state?
AgentNext to applications or on each machineCollect, label, forwardNo
Gateway, routing layerCentral group of collectorsReceive, light processing, route by keyNo
Gateway, stateful layerCentral group of collectorsTail sampling, aggregation, deduplicationYes

A Small Example

A company with five services and modest traffic runs one collector and everything works. After a year, traffic grows fifty times and the team wants to keep only interesting traces. One collector cannot hold all the traces in memory, so they add more. They then discover that the added collectors each see only part of every trace, which is the exact moment they need a routing layer.

2Core Concepts You Need First

A handful of terms will appear again and again in the rest of this guide.

Term 1

Exporter

The part of a collector that sends data out. It owns the connection to the next destination and handles retries and queues.

Term 2

Backend

In this context, one of the destination collectors that the load balancing exporter chooses from. Each backend is an endpoint with an address and port.

Term 3

Routing Key

The piece of identifying information used to choose a backend, such as a trace identifier or a service name. Same key, same backend.

Term 4

Resolver

The part that discovers which backends exist right now, for example by reading a fixed list or by asking DNS or Kubernetes.

Term 5

Consistent Hashing

A method of mapping keys to backends so that when the group changes, only a small share of keys move to a different backend.

Term 6

Two-tier Collector

An arrangement with a first layer that receives and routes data and a second layer that does the stateful work.

Why a trace identifier is such a good key

Every span in a trace carries the same trace identifier, which is a long random number created when the trace begins. Because it is random, identifiers spread out evenly across any group of backends. Because it is shared by every span in the trace, using it as the routing key sends the whole trace to a single backend. These two properties together are why the trace identifier is the default and most popular routing key for traces.

i
Remember

The exporter does not look at how busy each backend is. It does not measure load at all. It chooses by key, and the evenness of the spread comes from the keys being well mixed, not from the exporter watching the backends.

More vocabulary that helps

Term 7

OTLP

The OpenTelemetry protocol, the standard language that collectors and applications use to send telemetry to one another, usually over gRPC or HTTP.

Term 8

Pipeline

A chain inside a collector that connects receivers, processors and exporters for one kind of signal.

Term 9

Batch

A group of telemetry items sent together to save effort. Routing splits each batch into smaller ones.

Term 10

Hot Spot

A backend that receives far more work than its peers, usually because many items share the same routing key.

Term 11

Headless Service

A Kubernetes service that publishes one address for each pod instead of a single virtual address, so clients can see every member.

Term 12

Sticky Routing

Sending items with the same key to the same destination every time, as long as the group stays the same.

These terms sound technical, but each one maps to something simple. OTLP is the common language. A pipeline is an assembly line. A batch is a box of items. A hot spot is one overloaded worker. A headless service is a phone book that lists every person rather than only the switchboard. Sticky routing is the habit of sending the same customer to the same clerk. Keeping these pictures in mind will make the rest of the guide much easier to follow.

3What the Load Balancing Exporter Is

Now we can state the definition plainly.

The load balancing exporter is an exporter in the contributed part of the OpenTelemetry Collector ecosystem. Its job is to take incoming telemetry, split it into groups according to a routing key, and send each group to the backend that the key maps to. It keeps a separate connection to every backend, and it keeps that list of backends up to date by using a resolver.

Internally it builds on the standard OTLP exporter, which is the usual way of sending data between collectors. For each backend it creates one OTLP exporter with the same settings, and it then acts as a clever front door to this family of exporters. This means features such as encryption, compression, retries and sending queues behave in the way you already know from the ordinary OTLP exporter.

“The load balancing exporter is not about spreading work evenly. It is about keeping related data together while spreading unrelated data apart.”

What it is not

It is easy to mistake this component for a general traffic balancer, so it helps to say what it is not. It is not a replacement for a network load balancer. It does not measure the health or speed of backends. It does not guarantee perfectly equal shares. It does not store data. It does not process data in any way other than grouping and routing it. It is a routing exporter that gives you stickiness by key.

QuestionOrdinary load balancerLoad balancing exporter
Chooses a destination byConnection, round robin, or current loadThe routing key found inside the data
Keeps related data togetherNo, unless special rules are addedYes, by design
Understands telemetry contentsNo, it sees only network trafficYes, it reads trace identifiers, service names and similar fields
Typical homeNetwork infrastructureInside a collector pipeline
Best forStateless workStateful work such as tail sampling
!
Common Misconception

People sometimes put this exporter in front of a stateless gateway collector hoping to improve balance. It adds complexity and may even create hot spots, so use it only when related data truly must stay together.

What you configure, described in words

Setting up the exporter involves a small number of decisions, and it helps to see them as a short list of questions. First, which signals will pass through it: traces, logs, metrics, or a combination. Second, which routing key applies to each signal. Third, how will the backends be found, which means choosing a resolver and supplying its details, such as the hostname and port for DNS or the service name for Kubernetes. Fourth, how will the exporter talk to each backend, which means the protocol settings that mirror the ordinary OTLP exporter, including encryption, compression, timeouts, retries and queue size.

Because the per-backend settings are shared, every backend is treated the same. You cannot easily give one backend special settings. This keeps the design simple, and it also means that your configuration must work for the slowest or most demanding backend in the group.

Decision 1

Which Signals

Choose traces, logs, metrics or several. Each signal needs its own pipeline wiring and often its own routing key.

Decision 2

Which Key

Decide what must stay together. This choice has the biggest effect on correctness and on how evenly load is spread.

Decision 3

Which Resolver

Pick the discovery method that suits your platform and your tolerance for slow updates.

Decision 4

Which Transport Settings

Set encryption, compression, timeouts and queues, remembering that they apply to every backend.

i
Where to Look for Details

Exact option names and defaults belong to the version you run. Treat the component’s own documentation in the collector contrib repository as the source of truth, and use this guide to understand the reasoning behind the choices.

4Architecture and Components

The exporter is small, but it has several moving parts that cooperate.

flowchart LR
  A[Applications and agents] --> R[Tier 1 collectors with load balancing exporter]
  R --> B1[Tier 2 collector 1]
  R --> B2[Tier 2 collector 2]
  R --> B3[Tier 2 collector 3]
  B1 --> S[Tracing backend]
  B2 --> S
  B3 --> S
        
FIG 1 — A two-tier collector layout with a routing layer in front
Part 1

Router

Reads each batch of data, finds the routing key for every item, and splits the batch into smaller batches, one for each chosen backend.

Part 2

Hash Ring

A data structure that maps keys to backends. Backends are placed at many points around an imaginary circle, and each key lands on the next backend it meets.

Part 3

Resolver

Discovers the list of backend addresses and tells the router when the list changes.

Part 4

Per-backend Exporters

One OTLP exporter per backend, each with its own connection, sending queue and retry behaviour.

The tier one collectors are normally stateless and numerous. They receive data from applications or from agents running next to applications, perhaps do light processing such as adding labels, and then pass everything to the load balancing exporter. The tier two collectors are fewer and stateful. They hold the data for as long as needed, run the tail-sampling or aggregation logic, and send the final results to storage.

Simple Analogy

Tier one is the airport check-in hall with many desks, and tier two is the set of gates. The check-in desks do not fly the planes. Their only job is to send each passenger to the right gate, and a family travelling together must always be sent to the same one.

Sizing the two tiers differently

The routing tier and the stateful tier have very different needs, so they should be sized by different rules. The routing tier mostly spends processor time receiving data, reading keys and sending batches onward. Its capacity should follow the total volume of incoming telemetry. Because it holds almost no state, you can add or remove members freely, and it recovers instantly from restarts.

The stateful tier mostly spends memory. A tail-sampling processor must keep all the spans of every trace that has not yet been judged. The amount of memory therefore depends on how many traces arrive per second, how many spans each trace holds, how large each span is, and how long the processor waits before deciding. Doubling the wait roughly doubles the memory needed. Increasing traffic does the same.

TierMain resourceWhat drives the needScaling style
RoutingProcessor time and networkTotal incoming volumeFreely and quickly
StatefulMemoryTrace rate, trace size and decision waitSlowly and deliberately

Failure domains

Think about what happens when something breaks. If a routing tier member fails, the data it was holding is small and the other members carry on, so the loss is brief. If a stateful tier member fails, every trace it was still gathering is lost, which may be a large number. This is why many teams run the stateful tier on stable machines with generous limits and treat its restarts as events to plan, while treating the routing tier almost as disposable.

Simple Analogy

The routing tier is like the taxi rank outside a station: taxis come and go without anyone minding. The stateful tier is like the station’s baggage room: guests have left their belongings there, so you do not close it without warning.

5Routing Keys: How the Choice Is Made

The routing key decides which pieces of data stay together, so it deserves careful thought.

Routing keys differ by type of telemetry, and the available choices have grown over time. Check the documentation for the version you run, because exact names and options can change. The common ideas are described below.

Traces

For traces the default key is the trace identifier. All spans of a trace go to one backend, which is what tail sampling needs. A second option is the service name, in which case all spans produced by one service go to the same backend. This is useful for components that compute figures per service, such as request counts and latency for each service.

Logs

For logs the same ideas apply in simpler form. Routing by trace identifier keeps the logs that belong to one request together, and routing by service keeps one service’s logs together. Some versions offer further choices, such as routing by resource or by a chosen attribute.

Metrics

Metrics are more varied. Common choices include routing by service, by resource, by the metric name, or by a stream identity that represents one exact time series. Each choice keeps a different set of data together. Routing by metric name keeps every series of one metric on a single backend, while routing by stream identity keeps each individual series together, which spreads load more finely.

SignalTypical keyWhat stays togetherTypical purpose
TracesTrace identifierEvery span of one traceTail sampling
TracesService nameEvery span from one serviceService-level aggregation
LogsTrace identifier or serviceLogs of one request or one serviceCorrelation and grouping
MetricsService, resource, metric name or streamData sharing the chosen identityAggregation and conversion
!
Hot Key Warning

Routing by service name is convenient, but one very busy service sends all of its data to a single backend, which can overload it. A trace identifier spreads load far more evenly because it is random, so prefer it whenever your job allows.

A simple way to choose the key

Ask one question: what must the receiving collector see together in order to do its job correctly? If the answer is “every span of a trace”, use the trace identifier. If the answer is “every span from one service, so I can count requests for that service”, use the service. If the answer is “every point of one metric series”, use the stream identity. The key is never an arbitrary choice; it follows directly from the job downstream.

1

Name the downstream job

Write down what the stateful tier will compute, such as sampling decisions or per-service figures.

2

Find the smallest group that must stay together

Choose the finest key that still gives the job everything it needs. Finer keys spread load better.

3

Check how evenly that key spreads

Estimate whether any single value of the key will carry a large share of the traffic.

4

Test with real traffic

Compare data volume across backends in a test environment before relying on the choice.

Mixed pipelines

A single collector can handle traces, logs and metrics at once, and each signal can use a different key. For example, traces may be routed by trace identifier for tail sampling, while metrics may be routed by service for aggregation. The two do not need to agree, because they are separate pipelines. What matters is that every signal’s key matches the job its own downstream processor performs.

i
Keep It Fine-grained

When two keys would both work, choose the one with more distinct values. A trace identifier has millions of possible values, a service name has dozens. More values mean a smoother spread across the ring.

6Internal Working: The Consistent Hash Ring

The central trick is a mapping that survives change.

Suppose you have four backends and a simple rule: take the key, turn it into a number, divide by four, and use the remainder to pick the backend. This works, until the day you add a fifth backend. Now the remainder is calculated differently, and almost every key moves to a different backend. All the traces currently being gathered at their old homes suddenly have their remaining spans sent elsewhere. This is disastrous for stateful work.

Consistent hashing avoids this. Imagine a circle marked with a huge range of numbers. Each backend is placed on the circle at several points, found by hashing its name together with a counter. To route a key, you turn it into a number, find that number on the circle, and walk clockwise until you meet the first backend marker. That backend receives the key. When a backend is added, it takes over only the stretches of the circle just before its markers, and everything else stays where it was. When a backend is removed, only the keys it owned move to its neighbours.

flowchart TD
  K[Key such as trace identifier] --> H[Hash the key to a number]
  H --> P[Find that point on the ring]
  P --> W[Walk clockwise to the next backend marker]
  W --> B[Send data to that backend]
        
FIG 2 — How a key finds its backend on the hash ring
Simple Analogy

Picture a round table with seats and a few waiters standing at different spots. Each guest walks clockwise from their seat to the first waiter, who serves them. If a new waiter joins, only the guests between the new waiter and the one before them change servers. Everyone else keeps the waiter they had.

Why several markers per backend

If each backend had only one marker, the stretches of the circle between markers would differ widely in size, and some backends would receive far more keys than others. Placing each backend at many points averages out these differences, giving a much more even spread. The cost is a slightly larger ring and a slightly longer lookup, both of which are very small.

What consistent hashing does and does not give you

It gives you minimal movement when the group changes, and an approximately even spread for well-mixed keys. It does not give you perfect fairness, and it does not move any keys for load reasons. If one backend is slower than the rest, the ring keeps sending it its share. This is a deliberate trade, because moving keys would break the very stickiness the exporter exists to provide.

A worked example in words

Suppose you have four backends. With the simple remainder method, a key whose number leaves remainder two goes to the third backend. Now add a fifth backend. The same key, divided by five, may leave remainder four, so it moves. In fact, roughly four out of every five keys end up with a different backend. With a ring, adding the fifth backend takes over only about one fifth of the circle in total, scattered in small stretches, and those are the only keys that move. Four out of five keys stay exactly where they were.

The difference is dramatic for stateful work. Under the remainder method, adding a backend causes nearly every trace in progress to be split. Under the ring, only a fifth of them are affected, and often less because many traces finish before the change matters.

MethodShare of keys that move when going from four to five backendsEffect on traces in progress
Simple remainderAbout four fifthsAlmost all are split
Hash ringAbout one fifthA minority are split

Determinism across routers

Many routing collectors run side by side, and each builds its own ring. For stickiness to hold, every routing collector must build the same ring from the same list of backends and map every key to the same place. This works because the hashing is a fixed calculation: the same inputs always give the same result. It holds only if all routers see the same backend list. If two routers have different views of the list for even a short time, they will send the same trace to different backends during that time.

!
Disagreement Window

Resolvers on different routers refresh at slightly different moments. During a scaling event there is a brief window in which routers disagree about the list. This is one more reason why changing the stateful tier should be rare and gradual.

7Resolvers: Finding the Backends

The ring is only as good as its list of backends, and the resolver supplies that list.

Resolver 1

Static

A fixed list of addresses written into the configuration. Simple and predictable, but it changes only when someone edits the configuration and restarts or reloads.

Resolver 2

DNS

Asks a DNS name for its addresses at regular intervals. When the answer changes, the ring is rebuilt. A good match for environments where a name lists every backend.

Resolver 3

Kubernetes

Watches a Kubernetes service and its endpoints directly, so changes to the set of pods are noticed quickly, without waiting for a DNS refresh.

Resolver 4

Cloud Service Discovery

Some versions can discover backends through a cloud provider’s service-discovery product, which suits teams running on that platform without Kubernetes.

Choosing among them

ResolverHow quickly it notices changeNeedsBest when
StaticOnly after a configuration changeNothing externalThe set of backends rarely changes
DNSAt the refresh intervalA name that returns every backend addressBackends live behind a DNS name that lists them individually
KubernetesQuickly, as endpoints changePermission to read the service’s endpointsEverything runs in Kubernetes
Cloud discoveryDepends on polling settingsAccess to the provider’s discovery serviceYou run on that cloud without Kubernetes

A DNS subtlety that surprises beginners

For DNS discovery to work, the name must return the address of every backend, not a single virtual address that hides them. In Kubernetes this is usually done with a headless service, which publishes one address per pod. If you point the resolver at an ordinary service that returns only one virtual address, the exporter believes there is a single backend and sends everything to it, and the whole point of the arrangement is lost.

i
Practical Note

Whichever resolver you choose, watch the exporter’s own figures for the number of backends it believes exist. If that number is lower than expected, the resolver is almost certainly the cause.

Tuning the DNS resolver

The DNS resolver has a few settings worth understanding. The refresh interval controls how often the resolver asks for the current list of addresses. A short interval notices change quickly but increases the number of DNS queries. A long interval is gentler on DNS but leaves the ring out of date for longer. The timeout controls how long the resolver waits for an answer before giving up and keeping the previous list. A sensible timeout prevents a slow DNS server from freezing the routing tier.

Also remember that DNS answers are sometimes cached by the operating system or by intermediate servers. Even when the resolver refreshes often, a cached answer may still be returned. Check the caching behaviour of your platform so that the effective delay matches your expectations.

Tuning the Kubernetes resolver

The Kubernetes resolver watches the endpoints behind a named service and updates the ring as pods become ready or disappear. It needs the name and namespace of the service and the ports to use. Some versions can return hostnames instead of raw addresses, which is helpful when certificates are issued for names rather than addresses. Because it watches directly, it reacts faster than DNS, but it needs permission to read the relevant objects, so an access role must be created for it.

!
Readiness Matters

The set of endpoints usually includes only pods that report themselves ready. If a stateful collector takes a long time to become ready, it will be missing from the ring for that period, and the other members will carry its share. Make sure readiness reflects true ability to accept data.

When to use the static resolver

A static list is entirely suitable for small, stable setups, for example two stateful collectors on fixed machines. It has no moving parts to fail and is easy to reason about. Its weakness is that changes require editing the configuration. If you scale rarely and carefully, as recommended for the stateful tier, this weakness may be an acceptable price for simplicity.

Setting 1

Refresh Interval

How often the list is refreshed. Shorter means fresher but costs more queries.

Setting 2

Timeout

How long to wait for an answer, so a slow lookup cannot stall routing.

Setting 3

Ports

Which port each backend listens on for incoming data from the router.

Setting 4

Names or Addresses

Whether backends are referred to by hostname or address, which affects certificate matching.

8Data Flow and Lifecycle of One Batch

Following one batch of spans through the exporter makes the whole mechanism concrete.

sequenceDiagram
  participant App as Application
  participant T1 as Tier 1 collector
  participant LB as Load balancing exporter
  participant R as Resolver
  participant B1 as Backend 1
  participant B2 as Backend 2
  R-->>LB: Current list of backends
  App->>T1: Batch of spans
  T1->>LB: Pass batch to exporter
  LB->>LB: Read trace identifier of each span
  LB->>LB: Look up each key on the ring
  LB->>B1: Spans for traces mapped to backend 1
  LB->>B2: Spans for traces mapped to backend 2
  B1-->>LB: Acknowledgement
  B2-->>LB: Acknowledgement
        
FIG 3 — One batch of spans split and routed to two backends
1

The batch arrives

A mixed batch of spans, probably from many different traces, reaches the exporter through a pipeline.

2

Keys are extracted

For every span the exporter reads the configured routing key, such as the trace identifier.

3

The ring is consulted

Each key is hashed and matched to a backend, using the ring built from the latest resolver answer.

4

The batch is split

Spans are regrouped into one smaller batch per backend, so each backend receives only the spans it owns.

5

Sending and acknowledgement

Each smaller batch travels through that backend’s exporter, with its own queue and retries, and the exporter waits for the result.

An important detail is that splitting a batch costs a little processing, because every item must be inspected. For this reason the load balancing exporter is usually placed in a lightweight tier whose only duty is routing, and it is sized to cope with the full volume of incoming data.

Connections and fan-out

Every routing collector keeps a connection to every backend. If you have twenty routing collectors and ten stateful ones, that is two hundred connections. This number grows quickly with the sizes of both tiers. Each connection consumes memory and a small amount of processor time, and each carries its own queue. At very large sizes, connection counts and queue memory become real considerations, and some teams shard the arrangement into several independent groups to keep each group manageable.

Batch size and efficiency

Splitting a batch into many small ones reduces efficiency. If a batch of one thousand spans is spread across ten backends, each backend receives roughly one hundred spans per batch. Smaller messages cost more per item than larger ones because each carries fixed overhead. For this reason it is wise to build large batches before the routing step, for example by using a batch processor earlier in the pipeline, so that after splitting each backend still receives reasonably sized messages.

Fan-out
Connections grow with both tiers
Split
Each batch is divided per backend
Batch first
Build large batches before routing

Order inside a batch

The exporter groups items by backend, but the order in which different traces appear inside the original batch is not meaningful. Each backend receives its own group, and within it the items for each trace remain together. Downstream processors must not rely on a particular ordering across traces. This is normal for telemetry, but it is worth remembering when you design processing steps that look for patterns across neighbouring items.

i
Practical Note

If you notice many tiny export calls and rising processor use in the routing tier, inspect the batch sizes. Fixing batching is often the cheapest improvement available.

9The Classic Use Case: Tail Sampling at Scale

The exporter became famous because it makes tail-based sampling possible in a scaled-out system.

Tail sampling means deciding whether to keep a trace after it has finished, using facts such as whether it contained an error or how long it took. To do this, a collector must receive every span of a trace. If the spans of one trace are spread over three collectors, each collector sees only a fragment. One may see a fast, healthy fragment and discard it, while another sees the failing fragment and keeps it. The result is broken, misleading traces.

The load balancing exporter in tier one fixes this. By routing on trace identifier, it guarantees that all the spans of a trace reach one tier two collector, where the tail-sampling processor waits for the trace to complete and makes a sound decision. Only the traces chosen by the policies are then forwarded to storage.

Keep Errors and Slow Traces

A tail-sampling policy that keeps every trace containing an error, and every trace slower than a threshold, only works when each trace is whole. The exporter makes that so.

Combine with Limits

After keeping the important traces, a second policy can apply a limit or a percentage to the rest. The tier two collector holds everything it needs to enforce such rules fairly.

Share the Load, Keep the Traces Whole

Because traces are spread by random identifier, memory use and processing are spread across all tier two collectors, so the group scales out as traffic grows.

i
Connects to Head Sampling

Many teams place a head-based sampler, such as a rate-limiting sampler, inside the applications to cut volume cheaply, and use this two-tier arrangement for the smarter tail-based decisions on what remains. The two ideas work as stages in a series.

The decision wait: a central tuning knob

The tail-sampling processor must decide how long to wait after seeing the first span of a trace before judging it. If it waits too little, slow traces are judged before their later spans arrive, and the processor sees an incomplete and misleadingly fast trace. If it waits too long, memory fills with traces that are already finished but still waiting for the clock. The right value is slightly longer than your slowest ordinary request, and you can find it by looking at the distribution of trace durations in your system.

The routing tier plays a supporting role here. Because the routing tier only forwards data, it does not add meaningful delay. But network delays, retries and queues can make spans arrive late, so the decision wait should include a margin for these as well.

Policy ordering and cost

Tail-sampling policies are evaluated for each trace, and some are more expensive than others. A policy that checks the status of spans is cheap. A policy that inspects many attributes is more expensive. Placing cheap policies first and thinking carefully about which traces need the expensive ones helps keep the stateful tier’s processor use manageable.

1

Measure trace durations

Find how long your slowest normal traces take from first span to last.

2

Set the decision wait with margin

Choose a wait slightly above that duration, allowing for network and retry delays.

3

Estimate memory

Multiply traces per second, spans per trace, bytes per span and the wait to see the working memory needed.

4

Verify under load

Test with realistic traffic and watch memory and dropped-before-decision counts.

!
Memory Cliff

When the stateful tier runs short of memory, the processor may drop traces before deciding, and a protective memory limiter may begin refusing data. Both silently reduce the quality of your sample. Leave generous headroom and watch for these signals.

10Other Use Cases Beyond Tail Sampling

Anything that needs related data in one place can benefit.

Metrics from Spans

A component that turns spans into request counts and latency figures for each service needs all spans of a service in one place to produce correct totals. Routing by service name keeps them together.

Metric Aggregation and Conversion

Components that convert cumulative values into per-interval changes, or that combine series, need all points of a series on the same collector. Routing by stream identity keeps each series intact.

Log Correlation

Grouping logs by trace identifier before processing lets a downstream component attach or analyse all logs of one request together.

Deduplication

When duplicate data can arrive through different paths, sending items with the same identity to the same backend allows that backend to detect and remove duplicates.

Per-tenant or Per-team Processing

Routing by a resource attribute that names a team or customer lets each backend apply policies, limits or enrichment specific to the group it receives.

The shared theme is state. Wherever a processor needs to remember something about earlier items in order to handle later items correctly, the load balancing exporter provides the guarantee that the earlier and later items meet at the same place.

Choosing between routing and doing less

Before adding a routing tier for any of these uses, it is worth asking whether the stateful processing could be simplified or moved. Sometimes the same result can be reached by computing figures in the applications themselves, for example by recording request counts and latency as metrics at the source, instead of reconstructing them from spans later. Metrics recorded at the source are complete by nature and need no routing at all.

The routing tier earns its place when the logic truly needs to see data from many sources together, as tail sampling does. It is less compelling when the same information is available in a simpler form. Each extra tier carries ongoing costs in machines, monitoring and attention, so adopt it for clear reasons and review the reasons from time to time.

GoalOption that avoids routingOption that needs routing
Request counts per serviceRecord metrics inside each applicationDerive metrics from spans in a stateful tier
Keep error tracesNone for whole traces; head sampling cannot see errorsTail sampling behind a routing tier
Remove duplicatesFix the source of duplicationRoute by identity and deduplicate in one place
Per-team policiesSeparate pipelines per teamRoute by team attribute to shared backends

11Scaling Events: What Happens When Backends Change

The hardest moment for any stateful design is when the group changes size.

flowchart TD
  A[Resolver notices a backend was added or removed] --> B[Ring is rebuilt]
  B --> C[Most keys keep their backend]
  B --> D[A small share of keys moves]
  D --> E[Traces in progress may be split across two backends]
  E --> F[Some traces are judged on fragments]
        
FIG 4 — Consequences of a change in the set of backends

Consistent hashing keeps movement small, but small is not zero. When a backend is added, a fraction of keys, roughly one divided by the new number of backends, will move to the newcomer. For traces still in progress at that moment, the spans received before the change sit on the old backend, and the spans received afterwards go to the new one. The tail-sampling decision for those traces may then be made on incomplete evidence.

The same happens when a backend disappears, either through planned shutdown or sudden failure. In the sudden case the data held in that backend’s memory is also lost, because tail-sampling processors keep their working data in memory. Resolvers also differ in how fast they notice the loss, so for a short period the exporter may keep sending data to an address that no longer answers.

EventEffect on routingEffect on in-progress traces
Backend addedA small share of keys moves to itSome traces split between old and new homes
Backend removed gracefullyIts keys move to neighboursSome traces split; held data may be flushed or lost depending on shutdown handling
Backend crashesExports fail until the resolver noticesHeld data lost; retries may help with new data
Resolver returns a wrong or empty listRing may collapse or move heavilyWidespread splitting until the list is corrected

Ways to soften the impact

Scale tier two slowly and deliberately rather than letting an autoscaler add and remove members every few minutes. Prefer scaling during quiet periods. Give tail-sampling processors a decision wait long enough for normal traces to finish, but not so long that memory balloons. Make sure shutdown gives backends time to finish and flush work. Keep a metric of how many traces were judged on fragments so that you can see how much damage your scaling pattern causes.

!
Autoscaling Caution

Aggressive autoscaling of the stateful tier is one of the most common causes of broken traces. A system that adds and removes backends every few minutes will constantly reshuffle keys, and a steady fraction of traces will always be incomplete.

A gentle scaling routine

Because scaling the stateful tier is the riskiest operation, it helps to follow a routine. The goal is to keep the number of split traces small and to be able to explain any that occur.

1

Choose a quiet window

Pick a time when traffic is lowest, so fewer traces are in progress when keys move.

2

Add or remove one step at a time

Change the group by a small amount, because each change reshuffles a share of keys.

3

Wait for readiness

Let a new member become ready and be discovered by every router before the next change.

4

Drain departing members

Give a member being removed time to finish its waiting traces and flush its results before it stops.

5

Check the signals

Look at backend counts, failure rates and the number of traces dropped before a decision, then proceed only if all look normal.

Accepting a small, known loss

No routine removes the effect entirely. Teams that are comfortable with sampling usually accept that a small share of traces around a scaling event will be incomplete, and they record the times of such events so that engineers can explain an odd trace. The aim is not perfection but predictability: scaling events should be rare, scheduled and understood.

Blue and Green Stateful Tiers

Some advanced teams run a second, new stateful tier next to the old one and switch the routing tier’s list from old to new in one step. Traces already in progress finish on the old tier while new ones go to the new tier. This costs extra resources for a short time but gives a very clean change.

12Reliability: Queues, Retries and Failures

Because the exporter sits in the middle of a data path, its failure behaviour matters a great deal.

Per-backend queues and retries

Each backend has its own exporter with its own sending queue and retry rules. This isolation is helpful: if one backend becomes slow or unreachable, its queue fills and its retries pile up, but the other backends continue to receive data normally. A problem with one tier two collector does not stop the others from working.

The same isolation has a cost. A single unhealthy backend still owns a share of the keys, so data for those keys keeps heading to it. Once its queue is full, new data for that share is refused or dropped, while data for the rest flows on. The overall effect is that part of your traces vanish while the remainder looks healthy, which can be hard to notice without good monitoring.

Setting 1

Queue Size

A larger queue absorbs short slowdowns but uses more memory and holds data longer before it is sent.

Setting 2

Retry Behaviour

Retries with growing pauses handle brief failures, but long retry periods can hold data until it is stale.

Setting 3

Timeouts

Reasonable timeouts stop a stuck connection from blocking work indefinitely.

Setting 4

Memory Protection

A memory limiter in the pipeline protects the collector from running out of memory when backends slow down.

What the exporter does not do for you

The exporter does not actively probe each backend to see whether it is healthy, and it does not automatically move keys away from a struggling backend. Its view of the world is whatever the resolver reports. If a backend is alive according to the resolver but too slow in reality, the exporter keeps sending it data. Health must therefore be managed by the platform around it, for example through readiness checks that cause an unhealthy pod to be removed from the list the resolver sees.

i
Design Hint

Connect your readiness checks to the discovery mechanism. A backend that reports itself not ready should disappear from the resolver’s answer quickly, so the ring can shift its keys to healthy neighbours.

Back-pressure and memory protection

When a backend slows down, the exporter’s queue for that backend grows. Left alone, the growth could consume all memory in the routing collector and take it down, which would affect traffic destined for healthy backends too. A memory limiter processor, placed early in the pipeline, prevents this by refusing new data when memory use crosses a threshold. The upstream senders then retry or drop, depending on their own settings. This is back-pressure: the problem at the destination is communicated backwards rather than hidden.

Back-pressure is uncomfortable but healthy. It tells the whole system that capacity has been reached. The worst designs are those that hide the problem by buffering without limit, because the failure then arrives suddenly, all at once, and with a large amount of data lost.

Persistent queues

Some versions allow queues to be stored on disk instead of memory. A disk queue survives restarts of the routing collector, so data waiting to be sent is not lost when the process stops. The cost is slower handling, extra disk use, and operational care for the storage. For many teams, telemetry is valuable but not irreplaceable, and an in-memory queue is an acceptable choice. For others, such as those with audit duties, disk queues provide extra assurance.

Queue typeSurvives restart?SpeedOperational cost
In memoryNoFastLow
On diskYesSlowerNeeds storage and monitoring
i
Think About Loss in Advance

Decide, before an incident, how much telemetry loss is acceptable and for how long. That decision should drive queue sizes, memory limits and retry periods, rather than leaving them at defaults that nobody has examined.

13Advantages, Disadvantages and Trade-offs

Like every design choice, the exporter trades one set of problems for another.

Advantages

  • Keeps related data together, which makes tail sampling and similar jobs correct.
  • Allows the stateful tier to scale out across many collectors.
  • Moves only a small share of keys when backends change.
  • Reuses the familiar OTLP exporter, so security and retry options feel known.
  • Offers several ways to discover backends to suit different platforms.
  • Spreads load well when the routing key is random, such as a trace identifier.

Disadvantages / Trade-offs

  • Adds an extra tier, with extra machines to run, monitor and pay for.
  • Does not react to load, so a slow backend keeps its share of keys.
  • Scaling events still split a small share of traces.
  • Poorly chosen keys, such as a single very busy service, create hot spots.
  • Resolver mistakes can silently collapse everything onto one backend.
  • Needs thought about permissions, naming and network paths.

Is the extra tier worth it?

The honest answer depends on your needs. If you only need to receive and forward data, a simple setup with a standard load balancer is cheaper and easier. If you need tail sampling, span-derived metrics, or any other stateful processing across several collectors, the extra tier is the price of correctness. The exporter is therefore a tool you adopt when the requirement forces you to, not one you add for its own sake.

If you need…Then…
Simple forwarding and batchingUse a standard load balancer in front of stateless collectors
Tail sampling across several collectorsUse the load balancing exporter in front of the sampling tier
Span-derived metrics that are correct per serviceRoute by service so one collector sees all of a service’s spans
Maximum simplicity with modest trafficRun a single collector or a small fixed number and avoid a second tier

Cost in plain terms

Running a second tier is not free, and it helps to count the costs honestly. There are more machines to pay for, because the routing tier is additional to the stateful tier. There is more network traffic, because data crosses an extra hop, and in many cloud environments traffic between machines in different zones has a price of its own. There is extra work for the team, who must monitor, upgrade and secure one more layer.

There are also savings. Tail sampling reduces the amount of data stored, which can be a large share of an observability bill. Better decisions mean that engineers see the traces they need and not a flood of boring ones, which saves time during incidents. For many organisations the savings exceed the costs, but only for those that actually need the stateful behaviour.

Extra
Machines, network hops and operating effort
Saved
Storage and engineer time
Judge
Weigh both against real needs

Zone awareness

In a cloud with several zones, the exporter does not know which zone each backend lives in, and it does not prefer nearby ones. Keys are mapped by hash alone, so a large share of traffic will cross zones. If cross-zone traffic is costly or slow in your environment, consider placing both tiers within the same zone, or accept the cost as the price of consistent routing. Choosing a key by locality would break the very evenness and stickiness the ring provides.

14Security, Permissions and Governance

A routing layer sees all of your telemetry, so it deserves the same care as any critical system.

Encrypting the hop

Because the exporter builds on the OTLP exporter, it supports encrypted connections and client certificates to each backend. Telemetry often contains sensitive details such as user identifiers, internal addresses and parts of queries, so traffic between tiers should be encrypted, and the identity of both sides should be verified where possible. Remember that encryption must be set up for every backend, and that certificates must match the names or addresses the resolver supplies.

Permissions for discovery

Some resolvers need permission to learn about backends. The Kubernetes resolver, for example, must be allowed to read information about services and their endpoints. Grant it only what it needs and nothing more, and review the permission as part of your regular security checks. A resolver with too little permission fails to discover backends, while one with too much permission widens the damage if the collector is compromised.

Who may change the routing

The configuration of the routing layer decides where data goes and how it is grouped. A mistake or a malicious change could send data to the wrong place, stop it from arriving, or cause overload. Keep the configuration under version control, require review for changes, and restrict who may deploy them.

!
Privacy Reminder

Routing keys can themselves be sensitive. If you route by an attribute containing a customer name or similar detail, that value is used inside the pipeline, so treat it with the same care as the data it identifies and avoid placing personal values in keys where a random identifier would work.

Multi-tenant Considerations

When several teams share one set of collectors, routing by a tenant attribute can keep each team’s data separate for policy purposes. Combine this with limits so that one tenant cannot overwhelm the backend that owns its keys.

Certificates and names

Encrypted connections rely on certificates, and certificates are tied to names. When the resolver supplies raw addresses, the router connects to an address and must still check that the certificate presented belongs to the expected service. If certificates are issued for hostnames, but the resolver provides addresses, the check may fail. Use resolver options that return hostnames, or issue certificates that cover the addresses or a shared service name, and test the setup before relying on it.

Certificates also expire. A routing tier whose certificates expire quietly will stop sending data, and the failure will look like a network problem. Automate renewal and monitor expiry dates as you would for any other critical service.

Limiting what leaves the routing tier

The routing tier sees raw data from many sources, including data that has not yet been scrubbed. If your design includes a step that removes sensitive attributes, place it before the routing step, so that sensitive values are removed as early as possible and never travel across the second hop. This also reduces the volume of data to be routed, which saves effort.

1

Scrub early

Remove or mask sensitive attributes in the first tier, before data is routed.

2

Encrypt every hop

Use encrypted connections between tiers and verify the identity of both sides.

3

Renew automatically

Automate certificate renewal and monitor expiry dates.

4

Review access regularly

Check that discovery permissions and deployment rights are still the minimum needed.

15Monitoring the Exporter Itself

A routing layer that fails quietly can damage data without anyone noticing.

The exporter publishes internal measurements about its own behaviour. Names and details vary between versions, so check the documentation, but the ideas are consistent. Typical figures include how many times the resolver has run, how many backends the exporter currently knows about, how long exports to each backend take, and whether those exports succeeded or failed.

Signal 1

Number of Backends

Compare this against the number of tier two collectors you expect. A lower number means discovery is failing.

Signal 2

Resolution Activity

How often the resolver runs and whether it succeeds. Long silences or repeated failures signal trouble.

Signal 3

Backend Latency

How long each backend takes to accept data. One slow backend stands out when compared with its peers.

Signal 4

Backend Outcome

The share of exports that succeed or fail, broken down by backend, which reveals the single sick member.

1

Alert on a falling backend count

A sudden drop means pods vanished or discovery broke, and keys are being reshuffled.

2

Alert on backend failure rates

A single backend with high failures means part of your traffic is being lost.

3

Watch queue growth and memory

Rising queues are an early warning that a backend cannot keep up.

4

Compare load between backends

Large differences in data volume per backend suggest a hot key or a skewed ring.

Also monitor the tier two collectors for the effects of routing, such as memory use of the tail-sampling processor and the number of traces dropped before a decision was made. Together these show whether the exporter and the stateful tier cooperate well.

Building a useful dashboard

A good dashboard for this layer tells a story from left to right. On the left, show how much data enters the routing tier. In the middle, show how that data is divided among backends, ideally as one line per backend so that imbalance is visible. On the right, show what the stateful tier does with it, such as traces kept and traces dropped before a decision. Under these, show the health numbers: backend count, failure rate, queue length and memory use.

Panel 1

Incoming Volume

Spans, logs or metric points per second entering the routing tier, as the baseline for everything else.

Panel 2

Share per Backend

One line per backend, showing how much each receives. Wide gaps reveal hot spots or skew.

Panel 3

Failures and Queues

Failed exports and queue lengths by backend, so one sick member stands out immediately.

Panel 4

Decision Quality

Traces judged, kept and dropped before a decision, which shows how well the stateful tier is coping.

Include annotations for deployments and scaling events. Many puzzling changes in the graphs turn out to coincide with a change that someone made, and annotations let you see that at a glance. Teach the on-call engineers to read the dashboard, so that during an incident they quickly decide whether the problem lies in discovery, in a single backend, or in overall capacity.

i
Compare Peers

The most powerful view is a comparison between backends doing the same job. Any member that differs sharply from its peers in volume, failures or latency is the first place to look.

16Design Patterns and Anti-patterns

A few arrangements work again and again, and a few mistakes repeat just as often.

Helpful patterns

Pattern: Thin Routing Tier, Thick Stateful Tier

Keep tier one small in function and large in number, doing nothing but receiving and routing. Put all memory-hungry logic in tier two. This makes each tier easy to size and easy to scale.

Pattern: Headless Discovery in Kubernetes

Publish tier two through a headless service so that DNS returns every pod address, or use the Kubernetes resolver to watch endpoints directly.

Pattern: Slow, Scheduled Scaling of the Stateful Tier

Scale tier two on a deliberate schedule and in small steps, so that reshuffling of keys is rare and predictable.

Pattern: Separate Pipelines per Signal

Use separate pipelines and routing keys for traces, logs and metrics, because each has different needs for stickiness.

Harmful anti-patterns

ANTI-PATTERN-01 Avoid
Problem

Running tail sampling in several collectors without any routing, relying on a standard load balancer to spread spans.

Why It’s Harmful

Spans of one trace land on different collectors, so each collector decides on a fragment and the results are inconsistent and misleading.

Correct Approach

Place a load balancing exporter in front of the sampling tier and route by trace identifier.

ANTI-PATTERN-02 Avoid
Problem

Pointing a DNS resolver at a normal service name that returns a single virtual address.

Why It’s Harmful

The exporter sees one backend and sends everything to it, which overloads it and wastes the other collectors.

Correct Approach

Use a name that lists every backend, such as a headless service, or use the Kubernetes resolver.

ANTI-PATTERN-03 Avoid
Problem

Routing by service name when one service produces most of the traffic.

Why It’s Harmful

That service’s data all goes to one backend, which becomes a hot spot while others sit idle.

Correct Approach

Route by trace identifier where possible, or split very busy services into finer keys.

ANTI-PATTERN-04 Avoid
Problem

Letting an autoscaler resize the stateful tier freely, adding and removing collectors every few minutes.

Why It’s Harmful

Keys are constantly reshuffled, so a steady share of traces is always split or lost.

Correct Approach

Scale conservatively, on schedule, with long stabilisation periods and graceful shutdown.

17Best Practices and Common Mistakes

A checklist in plain language, drawn from everything above.

1

Use it only when state demands it

If the work is stateless, a standard load balancer is simpler and cheaper.

2

Pick the most random key that works

Trace identifiers spread load best. Use service or attribute keys only when the job needs them.

3

Make discovery return every backend

Check the number of backends the exporter reports and compare it with your expectation.

4

Scale the stateful tier slowly

Plan scaling events, avoid peaks, and allow graceful shutdown.

5

Protect the hops

Encrypt traffic between tiers, grant minimal discovery permissions, and review configuration changes.

6

Size both tiers from measurements

Routing tier capacity follows total incoming volume, and stateful tier memory follows data volume multiplied by the decision wait.

7

Monitor the exporter and its backends

Watch backend counts, failure rates, queues and per-backend load, and alert on change.

!
Frequent Mistakes

The most common errors are using a resolver that hides backends, routing by a hot key, autoscaling the stateful tier too eagerly, forgetting to encrypt the hop between tiers, and expecting the exporter to react to backend load. Each of these produces symptoms that are easy to misread, such as odd trace gaps or one overloaded pod.

A rollout approach that reduces risk

Introduce the second tier in a test environment first. Send a copy of real traffic through it, and check that traces arrive whole and that load is spread as expected across tier two. Then move a small slice of production traffic, compare results with your existing setup, and expand gradually. Keep the previous path available for a time so you can return to it if something looks wrong.

Tell the people who use traces what has changed. When sampling decisions move to a different place, the volume and shape of stored traces may change, and engineers will ask questions. A short explanation prevents confusion and builds trust in the new arrangement.

A review checklist before going live

Check 1

Key Fits the Job

The key keeps together everything the downstream processor needs, and no single key value carries a large share of traffic.

Check 2

Discovery Shows Every Backend

The backend count reported by the exporter equals the number of stateful collectors, in every environment.

Check 3

Hops Are Encrypted

Certificates match names, expiry is monitored, and renewal is automatic.

Check 4

Memory Is Protected

Memory limiters and queue sizes are set deliberately, and loss tolerance has been discussed.

Check 5

Scaling Is Planned

Changes to the stateful tier follow a written routine, with quiet windows and graceful shutdown.

Check 6

Monitoring Is Ready

Dashboards and alerts cover backend count, failures, queues, per-backend load and decision quality.

Going through this list with the whole team before the first production deployment catches most of the problems described in this guide. It also gives everyone a shared picture of how the system should behave, which makes later incidents shorter and calmer. Revisit the list after any large change to traffic, to the number of services, or to the platform that hosts the collectors.

18Real-World Scenarios

Some typical situations show where the exporter earns its place.

A Growing Online Retailer

Traffic has grown to the point where one sampling collector runs out of memory. The team adds more sampling collectors, but traces are now split between them. A routing tier using the load balancing exporter on trace identifier restores whole traces and lets the sampling tier grow with traffic.

A Platform Team Serving Many Product Teams

The platform runs an agent next to every application and a shared gateway. The gateway tier does light processing and routes to a stateful tier that applies sampling policies agreed with each team. The platform scales the stateful tier on a weekly review rather than automatically.

A Streaming Service with Spiky Traffic

Traffic jumps for popular releases. The routing tier scales quickly because it is stateless, while the stateful tier is sized for the expected peak in advance. This avoids reshuffling keys in the middle of the spike.

A Financial Firm with Strict Rules

Encrypted connections between tiers, narrow discovery permissions, and version-controlled configuration satisfy audit requirements. Tail sampling keeps all error traces for investigation, while separate audit logs record every transaction.

graph LR
  A[Steady traffic] --> B[Routing tier handles volume]
  C[Traffic spike] --> B
  B --> D[Stateful tier sized for peak]
  D --> E[Whole traces and stable sampling]
        
FIG 5 — Absorbing spikes in a stateless tier while keeping the stateful tier steady

Lessons that repeat across scenarios

In every case the successful teams treat the two tiers differently. They let the stateless routing tier scale freely and the stateful tier scale carefully. They use random keys when they can. They watch the number of backends and the failure rates. They accept that scaling events cause small losses and design their routines to keep those events rare.

A Software Company Moving from One Collector to Many

A company that began with a single sampling collector sees memory alarms during busy hours. The team introduces a routing tier, moves sampling to a stateful tier of four collectors, and chooses trace identifier as the key. They measure the share of traces judged on fragments during the first week, find it small, and decide to keep scaling changes to a weekly review.

A Team That Chose the Wrong Key

A team routed by service name because it seemed natural. One service made up most of the traffic, and the backend that owned it ran out of memory repeatedly while its peers stayed idle. Switching to the trace identifier spread the load evenly and ended the outages. The lesson is to test a key against real traffic before trusting it.

A Team That Hid Its Backends

A team pointed the DNS resolver at an ordinary Kubernetes service. The exporter saw one address and sent everything there. Only when they compared the number of backends reported by the exporter with the number of pods did they notice. Switching to a headless service fixed it.

What the scenarios teach together

Each of these stories came down to one of a few simple causes: a key that did not spread well, a resolver that did not show every backend, or a scaling pattern that disturbed the ring. All were found by watching the exporter’s own signals and comparing backends with their peers. All were easy to prevent with a short checklist and a test environment.

19Frequently Asked Questions

Short, plain answers to the questions people ask most often.

Q1Is the load balancing exporter part of the core collector?

No. It is part of the contributed components, which are distributed separately from the core. You need a collector build that includes it, which is usually done by choosing a contrib distribution or building a custom one.

Q2Does it measure how busy each backend is?

No. It routes by key using a hash ring. Evenness comes from the keys being well mixed, not from measuring load.

Q3Which routing key should I choose for traces?

Use the trace identifier when you need whole traces, for example for tail sampling. Use service name only when the job needs all spans of a service together, and accept the risk of hot spots.

Q4What happens when I add a backend?

The ring is rebuilt, and a small share of keys moves to the new backend. Traces in progress for those keys may be split between the old and new homes.

Q5Why does my exporter send everything to one backend?

Most often the resolver returns a single address, for example because a DNS name points to a virtual address instead of listing every pod. Check the backend count the exporter reports.

Q6Can I use it for metrics and logs as well as traces?

Yes. Each signal has its own choices of routing key, so check the documentation for your version and choose the key that keeps together what your downstream processing needs.

Q7Is it a replacement for a network load balancer?

No. A network load balancer spreads connections, while this exporter reads the data and routes by content. They solve different problems and are often used in different places.

Q8Which resolver should I use in Kubernetes?

Either a DNS resolver with a headless service or the Kubernetes resolver, which watches endpoints and notices change faster. The Kubernetes resolver needs permission to read endpoint information.

Q9What happens if a backend crashes?

Exports to it fail until the resolver stops listing it. Data held in its memory is lost. Other backends keep working, but the crashed backend’s share of keys is affected until the ring is updated.

Q10Does it slow my pipeline down?

It adds the small cost of reading keys and splitting batches. In a properly sized routing tier this is modest, and the benefit of correct stateful processing usually outweighs it.

Q11Can I run it without a second tier?

The exporter sends to other collectors, so a second tier is part of the idea. Without a stateful destination there is nothing for it to route to.

Q12How should I size the stateful tier?

Estimate the incoming data volume and the time that tail-sampling policies wait before deciding. Memory need grows with both. Measure in a test environment and keep headroom for bursts.

Q13Can I change the list of backends without restarting?

With dynamic resolvers, such as DNS or Kubernetes, the list updates as the environment changes. With a static list you must change the configuration and reload or restart.

Q14Is there an alternative approach?

Some teams route through a message queue partitioned by trace identifier, or through a proxy with consistent hashing. These can work, but the load balancing exporter has the advantage of being built into the collector and aware of telemetry formats.

20Summary and Key Takeaways

The load balancing exporter solves a specific and important problem: how to send related telemetry to the same collector when many collectors are available. It reads a routing key from each item, maps the key to a backend with a consistent hash ring, keeps one OTLP exporter per backend, and uses a resolver to keep the list of backends current. This makes it the natural front door for any stateful collector tier, most famously tail sampling.

Its strengths come with limits. It does not react to load, it cannot prevent every split trace when backends come and go, and it depends on the resolver supplying an honest list. Used with care, with a random key, an encrypted hop, a patiently scaled stateful tier and good monitoring, it provides the reliable foundation that scaled-out observability needs.

Key Takeaways

  • Related data stays together — the exporter routes by a key so that all items sharing the key reach the same backend collector.
  • Built for stateful work — tail sampling, span-derived metrics and series aggregation need whole data sets in one place, and this exporter provides that.
  • Consistent hashing limits disruption — when backends change, only a small share of keys move, though in-progress traces can still be split.
  • Resolvers decide what it sees — static, DNS, Kubernetes and cloud discovery supply the backend list, and a resolver that hides backends silently breaks the design.
  • It does not balance by load — evenness comes from random keys, so prefer trace identifiers and beware of hot keys such as one very busy service.
  • Scale the stateful tier carefully — slow, scheduled changes and graceful shutdown keep split traces rare.
  • Secure and monitor the hop — encrypt traffic, limit discovery permissions, and alert on backend counts, failures and per-backend load.