Multiple Pipelines in OpenTelemetry
How the OpenTelemetry Collector can run several independent assembly lines for your telemetry at once, so the same data can be cleaned, split, copied and delivered to different places in different ways.
Picture a busy restaurant kitchen. Orders arrive at one window, but they do not all follow the same path. The soup goes to one station, the grill items to another, the desserts to a third, and every plate is checked by a different cook before it leaves. If the kitchen had only one long counter where every dish had to be handled in the same order, the soup would wait behind the steak, and the dessert would be treated like a burger. Smart kitchens run several lines side by side, each shaped for the job it does.
The OpenTelemetry Collector faces the same situation with your monitoring data. Traces, metrics and logs arrive from many programs. Some of that data must be cleaned of private details, some must be sampled to save money, some must be sent to two different tools at once, and some must be turned into a different kind of data altogether. A single straight line cannot do all of that well. The Collector solves this with pipelines, and it lets you define as many of them as you need.
In this guide we start from zero. We explain what the Collector is, what one pipeline looks like, and then what changes when you have several. We cover how data is copied and merged between pipelines, how special parts called connectors link pipelines together, how the Collector builds and runs them inside, and how to scale, secure and monitor the result. Every new word is explained when it first appears, and each big idea comes with an everyday comparison.
1What Are Multiple Pipelines?
A pipeline is one assembly line for one kind of telemetry. Multiple pipelines simply means running several of these lines inside the same Collector.
OpenTelemetry is an open-source project that gives software a standard way to produce telemetry, the stream of information a program sends out about itself: what it did, how long it took, what went wrong. The OpenTelemetry Collector is a separate program that sits between your applications and your monitoring tools. It receives telemetry, changes it if needed, and forwards it onward. You can think of it as a sorting and packing centre for monitoring data.
Inside the Collector, the work is organised into pipelines. A pipeline is a fixed path with three kinds of stops. Data enters through a receiver, passes through zero or more processors that inspect or change it, and leaves through one or more exporters that send it to a destination. Every pipeline handles exactly one signal, which is a category of telemetry: traces, metrics or logs.
Multiple pipelines means that your Collector configuration defines more than one of these lines. They may handle different signals, such as one pipeline for traces and another for metrics. Or they may handle the same signal in different ways, such as one traces pipeline that keeps everything for an archive and a second traces pipeline that samples and removes private details before sending data to a vendor. The pipelines run at the same time, share the same program, and can even share parts.
What a pipeline is not
The word pipeline is used in many places in technology, so let us fence it in. A Collector pipeline is not a build or deployment pipeline for software. It is not the span processing chain inside an application’s SDK, although that has a similar flavour. It is a named path inside the Collector’s configuration file, listed under a section called service. Everything in this guide is about those Collector paths.
Think of a railway station with several platforms. Each platform has its own timetable and its own set of trains, yet they all share the same station building, the same staff and the same power supply. Passengers who arrive at the entrance are directed to the platform that suits their journey. Pipelines are the platforms of the Collector. The station is the single running program, and the platforms give each kind of journey its own track.
Why a single pipeline is not enough
A single pipeline works well for a small system with one destination. But real systems quickly collect extra needs. Different teams want different tools. Some data is sensitive. Some data is huge and must be sampled. Some destinations are slow or unreliable. When all of this is forced through one line, every rule applies to every item of data, and one problem can slow everything. Multiple pipelines give each need its own lane.
Even a very simple Collector setup usually has at least three pipelines, one for each of traces, metrics and logs. So the idea of multiple pipelines starts earlier than most people expect. This guide shows how to go beyond that starting point on purpose.
A simple mental model: three questions
When you meet any Collector configuration, three questions unlock it. First, where does the data come in? Look at the receivers. Second, what happens to it on the way? Look at the processors of each pipeline, in order. Third, where does it go out? Look at the exporters. Then repeat for each pipeline. With multiple pipelines, you simply ask the three questions several times and notice which parts repeat.
This method turns a long, intimidating file into a handful of short stories. Each pipeline is one story with a beginning, a middle and an end. The only extra thing to watch for is a connector, which is a place where one story ends and another begins. Once you see a connector, you follow the data into the next pipeline and carry on reading.
Example: reading a setup in one minute
You open a configuration and find four pipelines. Two carry traces, one carries metrics and one carries logs. All use the same OTLP receiver. The two traces pipelines differ in that one has a sampling step and the other does not. The metrics and logs pipelines share one vendor exporter. In under a minute you can explain the whole design: one door in, one archive path and one sampled path for traces, and a shared vendor path for the rest.
2The Problems Multiple Pipelines Solve
Every extra pipeline exists because one line could not meet two different needs at the same time.
Need 1: send the same data to more than one place
A company is moving from one monitoring tool to another. For three months it wants the data to reach both, so that engineers can compare the screens before they switch. Or a security team wants a full copy of every log in cheap storage, while the engineering team wants only the useful logs in an expensive search tool. Both cases require the same data to be delivered to several destinations.
Need 2: treat each destination differently
The archive wants everything exactly as it arrived. The vendor tool charges by volume, so it should get a sampled set. A partner should receive only data without customer details. If all of these shared a single line of processors, you could not give each one its own treatment, because whatever you did for one would also happen to the rest.
Need 3: derive new data from existing data
You may want request counts and durations calculated from your traces and stored as metrics. This turns one kind of data into another. It needs a path that begins as a traces pipeline and ends as a metrics pipeline, and the Collector provides this with a special part called a connector.
Need 4: keep one problem from spreading
If a destination becomes slow or goes down, data waiting for it can pile up. When many destinations share one line, a single sick destination can hold back healthy ones. Separate pipelines, each with its own buffers, help contain the damage.
Many destinations
Deliver the same data to several tools, such as an archive and a search tool, without changing the applications.
Different treatment
Sample, filter or redact data differently for each destination, so each gets what it should.
Derived data
Create metrics from traces, or counts from logs, and route them to the right place.
Isolation
Stop one slow or failing destination from blocking the rest.
flowchart LR subgraph One["One pipeline: one treatment for everyone"] A1["Receiver"] --> P1["Same processors"] P1 --> E1["Archive"] P1 --> E2["Vendor tool"] P1 --> E3["Partner"] end subgraph Many["Several pipelines: each tuned"] A2["Receiver"] --> Q1["Pipeline 1: keep all"] A2 --> Q2["Pipeline 2: sample"] A2 --> Q3["Pipeline 3: redact"] Q1 --> F1["Archive"] Q2 --> F2["Vendor tool"] Q3 --> F3["Partner"] end
A post office does not treat every item the same way. Ordinary letters go through one sorting line, large parcels through another, and registered mail through a third that records every handover. If everything went through the parcel line, letters would be slow and registered mail would lose its special handling. Each line exists because its items need different care.
More pipelines are not automatically better. Each one adds configuration to maintain and memory to use. Create a new pipeline only when you can name the need it serves, such as “the vendor must not see customer emails”.
3A Quick Refresher: The Collector and Its Parts
Five kinds of building blocks make up every Collector. Knowing their jobs makes everything else easy.
Signals
A signal is a category of telemetry. Traces follow one request through many services. Metrics are numbers measured over time, like requests per second. Logs are time-stamped records of events. A pipeline handles one signal only, so a traces pipeline never carries metrics. If you want all three, you define at least three pipelines.
The component types
| Component | Job | Everyday comparison |
|---|---|---|
| Receiver | Accepts data from outside, by listening for it or by fetching it | The goods-in door of a warehouse |
| Processor | Inspects or changes data on the way through | An inspection or packing station |
| Exporter | Sends data out to a destination | The loading dock |
| Connector | Joins two pipelines, acting as an exporter in one and a receiver in another | A conveyor belt between two lines |
| Extension | Adds helpful services that are not on the data path, such as health checks or credentials | The warehouse office and security desk |
The configuration file
The Collector is configured with a text file, usually written in a format called YAML. The file has sections. Separate sections define receivers, processors, exporters, connectors and extensions, giving each one a name and its settings. A final section called service then assembles them: it lists which extensions to run, and it declares the pipelines, each one naming which of the defined components it uses and in what order.
This split between “defining” and “using” is the key to multiple pipelines. A component defined once can be used in several pipelines, and a component that is defined but never used in any pipeline simply does nothing. We will build on this idea in every chapter that follows.
Where the Collector lives
The Collector can run in two common shapes. As an agent, it runs close to the applications, for example one copy on every server or every Kubernetes node. As a gateway, it runs as a central service that many agents and applications send to. Both shapes use the same pipelines idea. Large systems often use both, with an agent doing light work near the source and a gateway doing heavier shared work.
flowchart LR App["Applications with OpenTelemetry SDKs"] --> Agent["Collector as agent"] Agent --> Gw["Collector as gateway"] Gw --> B1["Backend A"] Gw --> B2["Backend B"]
Think of a recipe book and a kitchen schedule. The recipe pages describe individual dishes: how to make the sauce, how to roast the meat. The schedule says which dishes are cooked today and in what order. Defining components is writing the recipes. The service section is the schedule, and each pipeline is one meal on it.
The Collector comes in several distributions. Some contain only a core set of components, and others, such as the contrib distribution, contain many more. Always check that the components you want to use are present in the build you run, or the Collector will refuse to start.
Components come from distributions
You do not write receivers, processors and exporters yourself in normal use. They are shipped as ready-made components inside a Collector distribution, a packaged build of the Collector. A small core distribution contains the most common components. A larger contrib distribution adds hundreds of community-maintained ones, such as receivers for many data formats, exporters for many vendors, and the more specialised connectors. If you need only a few components, you can build a custom Collector that contains exactly those, which makes the program smaller and reduces what an attacker could reach.
Each component also has a stability level, such as alpha, beta or stable, and a list of the signals it supports. Both facts appear in its documentation. Reading them before you design your pipelines saves surprises, because a component that supports traces and metrics may not support logs, and an alpha component may change its settings in the next release.
4Anatomy of a Single Pipeline
Before multiplying, we must understand one. A pipeline has a signal, a start, a middle and an end.
The three stages
Data enters a pipeline at one or more receivers. A receiver speaks a protocol. The most common is OTLP, the OpenTelemetry Protocol, which is the standard language of OpenTelemetry. Others read data in the formats of older tools, or collect data by scraping, which means visiting a target on a timer and reading its numbers. A pipeline must have at least one receiver.
Data then flows through processors, in the exact order in which they are listed. A processor might drop data you do not want, add or remove labels, limit memory use, group small items into larger batches, or make decisions about sampling. A pipeline may have no processors at all, although production setups almost always have a few.
Finally data reaches exporters. An exporter converts the data to the format of its destination and sends it, with settings for retries and queues. A pipeline must have at least one exporter. Data that reaches the exporter stage is copied to every exporter listed, so one pipeline can already deliver to several destinations.
flowchart LR R["Receiver: OTLP"] --> M["Processor: memory limiter"] M --> A["Processor: add attributes"] A --> B["Processor: batch"] B --> X["Exporter: backend"]
Why order matters
Because processors run one after another, the order changes the result. If a filter that drops health-check traces sits before a step that adds labels, the labels are never wasted on data that gets dropped. If a batching step sits before a sampling step, the sampler sees data in lumps rather than individually. A widely used guideline is to place the memory limiter first, so it can protect the Collector before anything else uses memory, and to place batching near the end, so that the data is grouped just before it is sent.
What a pipeline is made of at runtime
When the Collector starts, it reads the configuration and builds each pipeline as a chain of live objects. The configuration is the plan, and the running objects are the building. A subtle point, which we meet properly in later chapters, is that the building is not built exactly as the plan suggests: some components are created once and shared, and others are created separately for each pipeline.
| Stage | Minimum | Typical content |
|---|---|---|
| Receivers | At least one | OTLP receiver listening for SDK data |
| Processors | None required | Memory limiter, filters, attribute changes, batching |
| Exporters | At least one | OTLP exporter to a backend, or a debug exporter while testing |
A car-wash tunnel is a good picture. The car drives in at the entrance, passes through stations for rinse, soap, brush and dry in a strict order, and leaves at the exit. Drying before rinsing would be pointless. In the same way, the order of processors is part of the design, and the entrance and exit are the receivers and exporters.
If you list a component in a pipeline but never define it, or define it with a mistake, the Collector will not start. This is helpful, because errors appear at once instead of silently losing data. Always read the first lines of the Collector’s output after a change.
5Defining Several Pipelines
Naming is the secret. A pipeline’s name has two parts, and the second part is what allows many of the same kind.
The type and the optional name
Each pipeline is identified by its signal type, optionally followed by a slash and a name of your choice. The signal type must be one of the known ones, such as traces, metrics or logs. If you need a second traces pipeline, you cannot repeat the same identifier, so you add a name: traces/archive and traces/vendor are two different pipelines that both carry traces. The part after the slash is only a label, so make it describe the purpose.
The same naming idea applies to components. You may define two OTLP exporters, one named otlp/archive and one named otlp/vendor, each with its own address and settings. The first part names the kind of component, and the second part tells your instances apart.
A planning table
Before you write any configuration, it helps to plan the pipelines as a simple table. The table below describes an imaginary setup that keeps a full copy of traces for an archive, and a sampled and cleaned copy for a vendor.
| Pipeline | Signal | Receivers | Processors in order | Exporters |
|---|---|---|---|---|
| traces/archive | Traces | otlp | memory limiter, batch | otlp/archive |
| traces/vendor | Traces | otlp | memory limiter, redaction, probabilistic sampler, batch | otlp/vendor |
| metrics | Metrics | otlp | memory limiter, batch | otlp/vendor |
| logs | Logs | otlp | memory limiter, redaction, batch | otlp/vendor |
Notice what the table shows. The same otlp receiver is listed in four pipelines, so it is defined once but used four times. The otlp/vendor exporter is used by three different pipelines. Only the processors and the archive exporter differ. This is the heart of multiple pipelines: shared ends, different middles.
Rules to remember
One signal per pipeline
A pipeline carries traces, metrics or logs. It never mixes them, except through a connector.
Names must be unique
No two pipelines may have the same full identifier, such as traces/archive. Add a name to make the second one different.
Receivers and exporters are required
Every pipeline needs at least one of each. Processors are optional.
Use only defined components
Every name that a pipeline lists must be defined in the sections above the service section.
Components must support the signal
A receiver, processor or exporter works only with the signals it was written for. Check the documentation of each component.
flowchart LR R["otlp receiver"] --> T1["traces/archive"] R --> T2["traces/vendor"] R --> M1["metrics"] R --> L1["logs"] T1 --> EA["otlp/archive exporter"] T2 --> EV["otlp/vendor exporter"] M1 --> EV L1 --> EV
A school timetable has classes named by subject and optionally by group, such as Maths for group A and Maths for group B. The subject is the type and the group is the name. The same teacher, the same classroom and the same bell system serve many classes. In the same way, one receiver and one exporter can serve many pipelines.
You can check a configuration without running the Collector in earnest. The Collector provides a validate command that reads the file and reports errors such as unknown components or missing definitions. Run it before every rollout.
Reading a multi-pipeline file, section by section
A configuration with several pipelines is easier to follow if you read it from the bottom up. Start at the service section. It tells you which pipelines exist, and for each one it lists the receivers, processors and exporters by name. Make a quick note of every name you see. Then go upward to the definition sections and find each of those names, reading its settings. You now know what each part is and how it is set.
Pay particular attention to three clues. The first is the second half of a name, after the slash. Names like otlp/archive and otlp/vendor tell you that the same kind of component was defined twice with different settings, usually different destinations. The second is a name used in more than one pipeline, which reveals what is shared. The third is a connector appearing in two pipelines, once among the exporters and once among the receivers, which reveals a link between pipelines.
| Clue in the file | What it tells you |
|---|---|
| Same receiver name in several pipelines | Fan-out: one door feeds many lines |
| Same exporter name in several pipelines | Fan-in: many lines share one outgoing connection |
| Two components of one kind with different names after the slash | Two destinations or two sets of settings |
| A connector listed as an exporter and as a receiver | A bridge between two pipelines, possibly between signals |
| A definition not listed in any pipeline | Unused, so it does nothing |
When you change a configuration, work in the same order. Edit the definitions first, then update the service section, then validate the file, and finally test with sample data. Most mistakes come from changing one half and forgetting the other.
6Fan-Out: One Receiver, Many Pipelines
When several pipelines list the same receiver, every piece of data that arrives is handed to all of them.
What fan-out means
Fan-out is the spreading of one stream into several. Imagine one hose with a splitter that feeds three garden beds. The Collector does exactly this when a receiver is listed in more than one pipeline of the same signal. The receiver is created once, listens on one port, and for every batch of data it receives, it passes the data to the start of each pipeline that uses it.
This is a powerful saving. Your applications send their data to one address only, and they do not need to know how many pipelines are behind it. You can add a new pipeline, say for an audit copy, without touching a single application. The change happens in the Collector alone.
flowchart LR S["Applications"] --> R["One OTLP receiver"] R --> P1["Pipeline A: archive everything"] R --> P2["Pipeline B: sample and send to vendor"] R --> P3["Pipeline C: filter errors for alerts"]
Do the pipelines share the same data?
A natural worry is that one pipeline may change the data and surprise the others. If pipeline B removes a label, does pipeline A lose it too? The Collector is built to prevent this. Components declare whether they mutate, which means change, the data they handle. When a stream fans out to several pipelines and at least one of them would change the data, the Collector makes copies so that each pipeline works on its own version. When no pipeline would change the data, the Collector can pass the same read-only data to all of them, saving memory and time.
The result is a simple rule you can rely on: pipelines do not affect each other’s data. A redaction in one pipeline never removes information from another. The cost is that copying uses memory and processor time, so very large fan-outs of heavy data should be planned with care.
Each pipeline gets its own processors
Another important fact is that processors are not shared between pipelines. If you list a batch processor named batch in three pipelines, the Collector creates three separate batch processors. Each one keeps its own pile of waiting data and its own timer. This matters most for processors that keep state, such as batchers, samplers and anything that counts. Two pipelines using the same processor name do not pool their data; they each work alone.
| Component | Shared or separate across pipelines? | What it means for you |
|---|---|---|
| Receiver | One instance, shared | One port, one set of connections, data copied to each pipeline |
| Processor | A separate instance in each pipeline | State is not shared; each pipeline batches and samples alone |
| Exporter | One instance, shared | Data from all pipelines using it flows into one place |
A photocopier at a school office feeds three teachers who each need a copy of the same notice. One person walks in with the original, and three copies come out. Each teacher may then highlight their own copy without affecting the others. The original is received once, and each teacher works on a private copy. That is fan-out with cloning.
Data arriving at a receiver is not duplicated at your application. You do not need to configure the SDK to send twice. Fan-out happens entirely inside the Collector, which keeps your applications simple.
A rough cost picture, with illustrative numbers
Let us work through an imaginary example to feel the cost of fan-out. Suppose a gateway receives 5,000 spans per second, and each span is about one kilobyte when held in memory. That is roughly five megabytes of fresh data every second. If three pipelines each need to change the data, the Collector makes copies, and for a short time up to three times that amount is in flight. Add the data waiting in each pipeline’s batch processor and each exporter’s queue, and the memory in use can be many times the size of the incoming stream.
These numbers are only an example, and real values depend on the shape of your data and your settings. But the lesson is general. Memory use grows with the number of pipelines that change data, and with the size of every buffer. Before adding a pipeline to a busy gateway, estimate its extra memory, set the memory limiter below the real limit of the machine, and watch the effect after the change.
You can reduce the copying cost by moving shared, data-changing work, such as removing noisy health-check spans, to the front of the design. Do it once before the data fans out, instead of repeating it in every branch.
7Fan-In: Many Pipelines, One Exporter
Fan-in is the mirror image. Several streams are merged into one outgoing connection.
Two kinds of fan-in
The first kind happens at the start of a pipeline. A pipeline may list several receivers, and data from all of them enters the same line. For example, one traces pipeline might accept data from an OTLP receiver and also from a receiver that understands an older tracing format. After that point, the data is treated identically no matter which door it used.
The second kind happens at the end. When several pipelines list the same exporter, the data from all of them flows into that one exporter. The exporter is created once, holds one connection and one queue, and sends everything it receives to its destination. This is efficient, because you do not open many connections to the same backend. It also means that the pipelines are mixed together at that point.
flowchart LR A["Pipeline: traces from services"] --> X["One exporter to the vendor"] B["Pipeline: traces from batch jobs"] --> X C["Pipeline: traces derived from logs"] --> X X --> V["Vendor backend"]
Why use separate pipelines before a shared exporter?
You might ask why anyone would build three pipelines that end in the same place. The reason is that the middles can differ. Traces from services may need careful sampling. Traces from batch jobs may need a different attribute added. Traces derived from logs may need filtering. Each pipeline applies its own rules, and then all the results leave through the same door.
The shared queue and its consequences
Many exporters have a sending queue, a waiting area that holds data while it is being sent, and retry settings that decide how to handle failures. Because the exporter is shared, all pipelines that use it share the queue and the retry behaviour. If the destination becomes slow, the queue fills with data from all of those pipelines, and when it is full, new data may be refused. A noisy pipeline can therefore crowd out a quiet but important one.
If this matters to you, give important data its own exporter. Define two exporters of the same kind with different names, such as otlp/critical and otlp/bulk, each pointing at the same destination, and give each its own queue size. Now the bulk data can fill its own queue without blocking the critical data.
Sharing an exporter
- Fewer connections to the destination.
- Simpler configuration, with settings in one place.
- Efficient use of memory for queues.
Separate exporters
- A slow stream cannot block a different stream.
- Each stream gets its own queue size and retry rules.
- More configuration and more connections to manage.
Think of several roads merging onto one bridge. The bridge is efficient because everyone shares it, but when one lane breaks down, traffic from every road backs up. A city that depends on one critical delivery route may build a second bridge dedicated to emergency vehicles. A separate exporter is that second bridge.
Do not assume that sharing an exporter keeps data from different pipelines apart at the destination. It does not. If the pipelines differ in how they treat data, you must add labels or choose different exporters if the destination needs to tell them apart.
8One Pipeline with Two Exporters, or Two Pipelines?
This is the most common design question. Both choices send data to two places, but they behave very differently.
The simple choice: two exporters in one pipeline
The easiest way to deliver the same data to two destinations is to list two exporters in one pipeline. Every item that reaches the end of the line is copied to both exporters. There is one set of processors, so both destinations receive data that was treated exactly the same way. This is perfect when both destinations should see the same data, such as when you send the same sampled traces to a primary and a backup tool.
The flexible choice: two pipelines
When the destinations need different treatment, you use two pipelines. Each has its own processors, and so each can sample, filter or redact on its own terms. The price is that you write and maintain more configuration, and some work, like batching, happens twice.
flowchart TD subgraph OneP["Design A: one pipeline, two exporters"] RA["Receiver"] --> PA["Shared processors"] PA --> EA1["Exporter 1"] PA --> EA2["Exporter 2"] end subgraph TwoP["Design B: two pipelines"] RB["Receiver"] --> PB1["Processors for destination 1"] RB --> PB2["Processors for destination 2"] PB1 --> EB1["Exporter 1"] PB2 --> EB2["Exporter 2"] end
| Question | One pipeline, two exporters | Two pipelines |
|---|---|---|
| Same treatment for both? | Yes, always | Not required; each can differ |
| Different sampling per destination? | No | Yes |
| Different redaction per destination? | No | Yes |
| Configuration size | Smaller | Larger |
| Memory use | Lower | Higher, because of copies and extra batchers |
| Failure isolation | Weaker: a slow exporter can hold back the other | Stronger: each line has its own buffers |
| Best for | Identical copies, such as primary and backup | Different needs, such as archive and vendor |
A short decision guide
Should both destinations see identical data?
If yes, start with one pipeline and two exporters. It is the simplest design that works.
Does any destination need different sampling, filtering or redaction?
If yes, use separate pipelines so each can have its own processors.
Is one destination slow or unreliable?
If yes, prefer separate pipelines and separate exporters with their own queues, so the problem stays contained.
Is the data huge?
If yes, count the cost of copies. Consider doing shared cleaning in a gateway first and then splitting.
Mailing the same letter to two friends can be done by photocopying one letter and posting both copies. That is one pipeline with two exporters. But if one friend needs a translated version and the other needs a version with private details blacked out, you must prepare two different letters. That is two pipelines.
You can combine both ideas. A common design uses shared processors up front, through a connector that merges them, then splits into specialised pipelines. The forward connector, described in chapter 10, is built for this.
9Pipelines for Different Signals
Traces, metrics and logs each need their own pipeline, and each signal has its own favourite tools.
One signal, one pipeline
A pipeline carries a single signal, so a full setup has at least one pipeline per signal. The three can share a receiver, since OTLP carries all three on the same port. They can also share an exporter, since an OTLP exporter can send all three to a backend that accepts them. What differs is the processors, because some processors only make sense for one kind of data.
Sampling and span work
Traces often need sampling, because they are large. A tail sampling processor waits for a whole trace to finish and then keeps the interesting ones, such as slow or failed ones. Filters can drop noisy spans such as health checks.
Temporality and cardinality
Metrics need care with the number of different label combinations. Processors can remove labels that create too many series, convert between cumulative and delta forms, or rename metrics.
Parsing and redaction
Logs often arrive as text that needs parsing into fields. They are also the most likely signal to hold private data, so redaction and filtering are common processors here.
Common processors
Some processors work on all signals: the memory limiter, the batch processor, resource detection and general attribute changes.
Why not one pipeline for everything?
The Collector does not allow it, and for good reason. A trace and a metric have completely different shapes. A processor that samples traces by trace identity has nothing to say about a metric. Keeping signals in separate pipelines keeps every component’s job clear and lets the Collector check at startup that you did not connect a traces-only component to a logs pipeline.
Several pipelines of the same signal
Within one signal, you may want more than one pipeline for the reasons we have discussed. A typical logs setup might have a pipeline for application logs, a pipeline for audit logs that must never be dropped, and a pipeline for debug logs that are heavily filtered. Each has its own filters and its own exporter, even though all three carry the same signal.
| Signal | Common processors | Typical extra pipeline |
|---|---|---|
| Traces | Memory limiter, filter, tail sampling, batch | A full-fidelity copy for the archive |
| Metrics | Memory limiter, attribute removal, aggregation, batch | Business metrics sent to a different tool |
| Logs | Memory limiter, parsing, redaction, filter, batch | Audit logs that bypass sampling |
A hospital has separate departments for blood tests, X-rays and consultations. All three share the reception desk and the building, which are like a shared receiver and exporter. But each department uses its own equipment and rules, and the X-ray room does not run blood tests. Within the blood department you may even have a fast lane for emergencies.
Check each component’s documentation for the signals it supports and its stability level. A processor that supports traces may not support logs, and the Collector will report an error if you use it where it is not supported.
Designing each signal on purpose
A good habit is to design the three signals one at a time, asking the same questions of each. For traces, ask how much you can afford to keep, whether any spans are noise, and whether a full copy must be archived. For metrics, ask which labels create too many different series, and whether you need derived metrics from traces or logs. For logs, ask where private data may hide, which severity levels are worth paying for, and whether any logs, such as audit records, must never be dropped.
Writing down these answers before you write any configuration turns a vague wish into a clear plan. It also shows you quickly where two signals need the same treatment, such as the same memory limiter and batching, and where they need different treatment, such as sampling for traces and parsing for logs.
Example: three signals, three answers
ShopFast answers the questions like this. Traces: keep all errors, sample a small share of normal traces, drop health checks, archive everything. Metrics: remove the user identifier label, and create request-rate metrics from traces. Logs: parse the text into fields, mask emails, never drop audit logs. Each answer becomes one or two pipelines, and the whole design fits on one page.
10Connectors: Bridges Between Pipelines
So far, pipelines have lived side by side without talking to each other. Connectors let one pipeline hand data to another.
What a connector is
A connector is a component with two faces. In one pipeline it acts as an exporter, and in another pipeline it acts as a receiver. Data that leaves the first pipeline through the connector enters the second pipeline through it. In between, the connector may simply pass the data along, or it may change it, or it may even create new data of a different signal.
The signals matter. A connector declares which signals it accepts on its exporter side and which it produces on its receiver side. A connector that turns traces into metrics is listed as an exporter in a traces pipeline and as a receiver in a metrics pipeline. This is the only way that data can cross from one signal to another inside the Collector.
flowchart LR R["OTLP receiver"] --> T["Traces pipeline"] T --> E["Vendor exporter for traces"] T --> C["Connector: spanmetrics"] C --> M["Metrics pipeline"] M --> E2["Vendor exporter for metrics"]
Common connectors
| Connector | From and to | What it does |
|---|---|---|
| spanmetrics | Traces to metrics | Computes request counts and durations from spans, grouped by labels such as service and operation |
| count | Traces, metrics or logs to metrics | Counts items, for example the number of error logs |
| servicegraph | Traces to metrics | Builds metrics that describe how services call each other |
| forward | Same signal to same signal | Simply passes data from one pipeline to another, used to merge or chain pipelines |
| routing | Same signal to several pipelines | Sends data to different pipelines depending on its contents |
| failover | Same signal to ranked pipelines | Tries pipelines in priority order and moves to the next if one fails |
The list of available connectors grows over time, and their stability levels differ. Some are mature, and others are still marked alpha or beta. Check the documentation for the version of the Collector you use before you depend on one.
The forward connector as glue
The forward connector deserves special mention, because it makes complex designs tidy. Suppose three different pipelines all need the same shared cleaning step before they split into different treatments. You can send all three into the forward connector, which feeds a single pipeline that does the cleaning, and then fan out again. This avoids repeating the same processors in each pipeline.
Rules for connectors
Use it on both sides
A connector must appear as an exporter in at least one pipeline and as a receiver in at least one other. A connector used on only one side is an error.
Match the signals
The signal of the pipeline on each side must match what the connector supports.
Avoid loops
Pipelines connected in a circle would send data around forever. The Collector checks for cycles and refuses to start.
Mind the volume
A connector that creates metrics from traces can produce many series if the labels vary widely. Choose labels with few possible values.
A factory has a line that makes bicycles and another that packs boxes. A conveyor belt runs from the bicycle line into the packing line. A bicycle leaves one line and arrives at the other without anyone carrying it by hand. A connector is that conveyor. Some conveyors also have a camera that counts every bicycle passing; the counts go to a different board. That is a connector that creates new data.
Before connectors existed, people made metrics from traces with a separate processor. Connectors replaced that approach, because a processor works inside one signal, while a connector is allowed to cross signals cleanly.
The failover connector in practice
The failover connector solves a different problem from routing. Instead of choosing a pipeline by the content of the data, it chooses by the health of the destination. You give it a ranked list of pipelines. All the data goes to the first pipeline while it works. If the first pipeline starts to fail, because its exporter cannot reach the destination, the connector switches the data to the second pipeline, and later it can switch back when the first recovers.
A typical use is a primary and a backup destination. The primary pipeline sends to the main vendor. The backup pipeline sends to a second location, such as a cheaper store or another region. During an outage at the primary, no data is lost, and the team can read it from the backup later. Failover is different from sending to both at once. It uses only one path at a time, so it costs less, but it relies on detecting failure quickly.
flowchart LR
In["Traces pipeline"] --> FC{"Failover connector"}
FC -- "priority 1" --> P1["Primary pipeline"]
FC -- "priority 2" --> P2["Backup pipeline"]
P1 --> E1["Main vendor"]
P2 --> E2["Backup store"]
Failover reacts to errors that the exporter reports. If an exporter hides failures in a long queue, the connector may notice late. Choose queue sizes and retry settings that let failures show up quickly, and test the switch by cutting off the primary on purpose in a safe place.
11Routing Data to the Right Pipeline
Sometimes the question is not “send it everywhere” but “send it to the right place”. Routing answers that.
The routing connector
The routing connector looks at each item of data and decides which pipeline should receive it. You give it a list of rules. Each rule has a condition, written in a small language for working with telemetry, and a target pipeline. Data that matches a condition goes to that pipeline. Data that matches no rule goes to a default pipeline, so nothing is silently lost.
An older component called the routing processor did a similar job, but it has been replaced by the connector, and new designs should use the connector. Because a connector sits between pipelines, it can feed full pipelines with their own processors and exporters, which is more flexible than a processor could be.
flowchart LR
In["Incoming traces pipeline"] --> RC{"Routing connector"}
RC -- "tenant is team-a" --> A["Pipeline for team A"]
RC -- "tenant is team-b" --> B["Pipeline for team B"]
RC -- "no match" --> D["Default pipeline"]
A --> EA["Exporter for team A backend"]
B --> EB["Exporter for team B backend"]
D --> ED["Exporter for shared backend"]
Typical routing needs
Multi-tenant platforms
A platform team serves many product teams. Data carrying a team label is routed to that team’s own backend or account.
Data residency
Rules require that data from one region stays in that region. Routing sends each item to the exporter inside the correct region.
Important versus bulk
Errors and critical services go to a pipeline with strong guarantees, while routine data goes to a cheaper one.
Private data
Logs marked as sensitive go to a pipeline that removes fields and sends only to approved storage.
Routing and tail sampling: a trap
Tail sampling, described in the signals chapter, needs to see all the spans of a trace in one place before it can decide. If spans from the same trace are scattered over several Collector instances, no instance sees the whole trace, and the decisions are wrong. Routing inside one Collector is fine, but when you run many gateway copies behind a load balancer, you must make sure that all spans of one trace reach the same copy. A special exporter, called the load balancing exporter, does this by sending data to a chosen copy based on the trace identity. A two-layer design, with an outer layer that routes by trace and an inner layer that does tail sampling, is the standard solution.
| Goal | Tool | Notes |
|---|---|---|
| Send items to different pipelines by content | Routing connector | Include a default route |
| Keep all spans of a trace on one Collector instance | Load balancing exporter | Needed before tail sampling across several instances |
| Fall back to another destination on failure | Failover connector | Ranks pipelines by priority |
| Merge pipelines before a shared step | Forward connector | Reduces repeated processors |
A postal sorting machine reads the address on each letter and drops it into the right bin for its region. Letters with unreadable addresses go to a manual bin. The routing connector is the sorting machine and the default pipeline is the manual bin. If a bundle of related letters must all arrive at the same office, a sorter first groups them by bundle, which is the job of the load balancing exporter.
Always include a default route. Without one, data that matches no rule has nowhere to go and may be dropped, and nothing will tell you. A default pipeline that exports to a catch-all place is a cheap safety net.
12How It Works Inside: Building and Running the Graph
The configuration file looks like lists, but the Collector turns it into a graph of connected parts. Understanding that graph explains almost every behaviour you will see.
From text to a graph
When the Collector starts, it reads the configuration and checks it. It confirms that every component named in a pipeline is defined, that every component supports the signal of the pipeline it is in, and that connectors appear on both sides. It then builds a graph: a map of nodes, which are components, and arrows, which show where data flows. Receivers and connectors that are used in several pipelines become single nodes with several outgoing arrows. Exporters used in several pipelines become single nodes with several incoming arrows. Processors, as we learned, are created separately for each pipeline.
Because it is a true graph, the Collector can also check it for problems. A connector loop, where data could go round and round, is detected and rejected. A component defined but never used in any pipeline is simply left out and never started, which is why unused definitions are harmless but also easy to forget.
Start order and stop order
The order in which the parts start matters. The Collector starts the parts at the end of the line first: exporters, then processors, then receivers. This means that by the time a receiver begins accepting data, everything downstream is ready to handle it. When the Collector shuts down, it reverses the order. It stops the receivers first, so no new data arrives, then lets the processors finish what they hold, and finally stops the exporters after they have sent their remaining data. This careful order helps prevent data loss during restarts, although a sudden crash can still lose data that was waiting in memory.
Data moves by direct hand-off
Inside the Collector, each component passes data to the next by calling it directly. A receiver takes in a batch of data and calls the first processor. That processor does its work and calls the next, and so on until the exporter is called. The consequence is that, unless a queue sits in between, the receiver’s call does not finish until the data has been handled further down. A slow component therefore slows the receiver, and an error deep in the chain can be reported back to the sender. This direct hand-off is what gives the Collector its back-pressure behaviour, which we meet in the scaling chapter.
flowchart TD Cfg["Configuration file"] --> Check["Validate components, signals and connectors"] Check --> Graph["Build the pipeline graph"] Graph --> S1["Start exporters"] S1 --> S2["Start processors"] S2 --> S3["Start receivers"] S3 --> Run["Run: data flows through the graph"] Run --> Stop["Stop: receivers first, exporters last"]
The life of one batch of data
The receiver accepts a request
An application sends a batch of spans. The receiver decodes it into the Collector’s internal form.
The fan-out step runs
If the receiver feeds several pipelines, an internal fan-out component hands the data to each, cloning it where a pipeline would change it.
Processors run in order
Each pipeline’s processors do their work in the listed order: memory check, filters, label changes, sampling, batching.
The exporter queues the data
The exporter places the data in its sending queue, if one is enabled, and answers that it was accepted.
The exporter sends and retries
Worker routines send the data to the destination. If sending fails, the retry rules decide how often to try again, and when to give up.
Connectors may start new work
If a connector is in the path, the data leaves one pipeline and enters another, which then repeats steps 3 to 5 with its own components.
Think of opening a restaurant for the evening. A sensible manager first checks that the dishwashers and cooks are ready, and only then opens the front door to customers. At closing, the manager locks the door first, lets the kitchen finish the meals already ordered, and switches off the dishwashing last. The Collector’s start and stop order follows the same common sense.
The internal details, such as how cloning is done, can change between releases. What you can rely on is the visible behaviour: pipelines do not change each other’s data, processors are per pipeline, and receivers and exporters are shared.
Reading the startup output
The first seconds of the Collector’s own output tell you whether your graph was built as you intended. Look for lines that name each pipeline and its components as they start. If a pipeline you wrote does not appear, it was probably not listed in the service section. If a component fails, the message normally says which one and why, for example that it does not support the signal of the pipeline you placed it in. If there are no errors, the Collector will say that it is ready to process data.
It is also worth checking what the Collector says about the components it was built with. A Collector distribution contains only certain components. If the configuration mentions a component that is not in your build, the Collector will refuse to start and tell you the name is unknown. The fix is to use a distribution that includes it, or to build a custom Collector with exactly the components you need.
Example: the pipeline that never ran
A team adds a new logs pipeline for audit records and deploys it. Weeks later, an auditor asks for the records and finds none. The team had defined all the parts but forgot to list the new pipeline in the service section, so it never started. The startup output would have shown only the old pipelines. A deployment check that compares the expected pipeline names with the ones that started would have caught the gap on day one.
13Performance, Scaling and Reliability
More pipelines mean more work. This chapter shows how to keep a multi-pipeline Collector fast, steady and safe from data loss.
Protect memory first
Every copy of data in a fan-out takes memory, and every batcher and queue holds data waiting for its turn. A Collector that runs out of memory is restarted by its host, and data in memory is lost. The memory limiter processor guards against this. It watches the memory use of the Collector, and when use passes a soft limit it starts refusing new data, and when it passes a hard limit it forces cleaning. Because refusing data pushes the problem back to the sender, the senders must be prepared to retry. Put the memory limiter first in every pipeline.
Batching and queues
Sending data one item at a time would be wasteful. The batch processor groups items, so the exporter sends fewer, larger requests. Remember that each pipeline has its own batch processor, so ten pipelines mean ten batchers, each holding a little data. Exporters add a sending queue that absorbs short slowdowns of the destination and retry rules that handle brief failures. For important data, a persistent queue, backed by a storage extension that writes to disk, lets data survive a restart of the Collector.
| Tool | What it protects against | Cost |
|---|---|---|
| Memory limiter | Running out of memory under spikes | Refuses data at the limit, so senders must retry |
| Batch processor | Too many small requests | Adds a small delay and holds data briefly |
| Sending queue | Short slowdowns of the destination | Uses memory, and loses data on crash unless persistent |
| Retry rules | Brief failures and network blips | Can build up queues if failure lasts |
| Persistent queue | Restarts and crashes | Uses disk and adds a little latency |
Back-pressure and isolation
Back-pressure is what happens when downstream parts cannot keep up and the slowness travels back toward the source. With separate pipelines and separate exporters, each with its own queue, the slowness of one destination fills only its own queue. With a shared exporter, the queue is shared, and everyone feels it. Isolation is therefore a design choice: give important and bulky data their own exporters, and decide what should happen when each queue is full.
Scaling out with agents and a gateway
A single Collector has limits. When load grows, you run several copies behind a load balancer. Most pipelines scale easily in this way, because each batch of data is independent. Two kinds of work are different. Tail sampling needs all spans of a trace in one place, and metrics derived from traces, such as those produced by the spanmetrics connector, are computed per copy, so each copy produces only a partial count. For both, route by trace identity or add a label that identifies the producing copy, so that the partial results can be combined later.
flowchart LR Apps["Applications"] --> Ag["Agent Collectors: light pipelines"] Ag --> LB["Load balancing exporter"] LB --> G1["Gateway copy 1: tail sampling and routing"] LB --> G2["Gateway copy 2: tail sampling and routing"] G1 --> Back["Backends"] G2 --> Back
Reliability patterns
Several gateway copies
Run at least two copies behind a load balancer, so one failure does not stop delivery.
Failover connector
Try a primary pipeline first, and automatically use a backup pipeline when the primary fails.
Persistent queues
Store waiting data on disk for the important pipelines, so a restart does not lose it.
Sender retries
Make sure SDKs and agents retry when the gateway refuses data under load.
A water system has a pressure valve, storage tanks and spare pipes. The valve stops pressure from bursting the pipes, the tanks cover short interruptions, and the spare pipes take over if one breaks. The memory limiter, queues and failover pipelines are the valve, tanks and spare pipes of your telemetry.
An unbounded queue is a hidden danger. If the destination is down for hours, a queue with no limit grows until the Collector runs out of memory. Always set sensible limits, and decide in advance whether it is better to drop data or refuse it when the queue is full.
14Security, Monitoring and Cost
Multiple pipelines let you treat data differently for safety, but they also multiply what you must watch and pay for.
Security: one pipeline per trust level
Telemetry often holds private details, such as email addresses in logs, account numbers in span labels or secrets in URLs. Not every destination should receive them. A good design uses a separate pipeline for each trust level. The internal archive, which sits in your own protected storage, may keep the full data. The pipeline for an outside vendor first removes or masks sensitive fields, using processors that delete labels, replace patterns or apply a redaction list. A partner pipeline might allow only a short, approved list of fields.
Redact before leaving
Sensitive fields are removed in the pipeline of any destination outside your control, before the exporter runs.
Separate credentials
Each exporter uses its own credentials, supplied through an authentication extension, so a leaked key exposes only one destination.
Encrypt in transit
Use TLS on receivers and exporters, so data is not readable on the network.
Allow-lists beat block-lists
For the most sensitive destinations, keep only listed fields rather than trying to remove every risky one.
Monitoring the Collector itself
A Collector that fails quietly is dangerous, so watch it. The Collector reports its own metrics about what each component does. They include counts of items accepted by receivers, items sent by exporters, items refused or dropped, items that failed to send, and the current size of exporter queues. Exact names change between versions, but the idea is stable: compare what came in to what went out, per pipeline. If the numbers do not match and you did not intend to drop data, something is wrong.
The Collector can also offer a health check extension that load balancers use to see whether a copy is alive, and a diagnostic page extension that shows live details of its pipelines. For new setups, a debug exporter prints a summary of data to the Collector’s own output, which is invaluable for confirming that a pipeline receives what you expect.
| Question | What to watch |
|---|---|
| Is data arriving? | Items accepted by each receiver |
| Is data leaving? | Items sent by each exporter |
| Is data being lost? | Items refused, dropped or failed to send |
| Is a destination struggling? | Queue size and retry counts for that exporter |
| Is the Collector healthy? | Memory use, processor use and health check result |
Cost: copies cost money
Sending the same data to two vendors can double your data transfer charges, and each vendor may bill you for the volume it ingests. Archive storage adds its own fee. Extra pipelines also use more memory and processor time in the Collector. The best defence is to be deliberate: sample before sending to expensive tools, drop data nobody uses, remove labels that create endless variety, and compare the cost of each pipeline against the value of the destination it feeds.
When you run two vendors side by side during a migration, put a clear end date on the duplicate pipeline. Many companies pay for a second tool for months longer than they intended simply because nobody removed the extra exporter.
Think of sending registered mail. Every extra copy of a letter costs a stamp, and every recipient may need a different envelope. If a letter contains private information, you blank it out before posting it to someone outside the family. A pipeline per destination is a planned way of preparing each envelope, and the postage bill reminds you to send only what is worth sending.
A pre-release checklist
Before you release a new multi-pipeline configuration to production, walk through a short checklist. Each item takes a minute and prevents a common kind of incident.
- Validation: the file passes the Collector’s own validation without errors.
- Coverage: every intended pipeline is listed in the service section, and every defined component is used by at least one pipeline.
- Privacy: every pipeline that sends data outside your control includes the redaction steps, and a sample run has been inspected by a person.
- Limits: the memory limiter is first, queue sizes are bounded and retry rules are set on purpose.
- Routing: each routing connector has a default route.
- Monitoring: a dashboard and an alert exist for items received versus items sent in each pipeline.
- Rollback: the previous working configuration is saved and can be restored quickly.
15Advantages, Disadvantages and Trade-offs
Several pipelines give you control. Control has a price, and an honest look at both sides prevents over-building.
Advantages
- Each destination gets exactly the treatment it needs.
- Applications stay simple and send once to one address.
- Sensitive data can be cleaned for outside destinations only.
- Derived data, such as metrics from traces, is created in one place.
- Failures and slow destinations are contained.
- Moving between vendors is easier, since you can run both for a while.
Disadvantages
- More configuration to write, review and test.
- Higher memory and processor use because of copies and extra batchers.
- Harder to understand at a glance as the graph grows.
- Shared exporters can hide problems between pipelines.
- Some connectors are still young and may change.
- Duplicate data raises transfer and vendor costs.
Trade-offs you will face
| Choice | Benefit | Cost |
|---|---|---|
| Many small pipelines | Clear purpose and easy isolation | More memory and more configuration |
| Few pipelines with shared parts | Simple and cheap | One treatment for everyone |
| Shared exporter | Fewer connections | One queue shared by all senders |
| Separate exporters per stream | Strong isolation | More connections and settings |
| Process once, then split with a connector | Avoids repeating work | Adds one more hop to understand |
| Do everything in the gateway | One place to manage rules | The gateway becomes critical and heavy |
| Do light work in agents | Spreads load, cuts network traffic early | Rules are spread across many places |
Ordering from a restaurant, you can choose one set menu or a la carte. The set menu is easy to run and cheap, but everyone eats the same thing. A la carte lets each guest choose, but the kitchen needs more staff and the bill is larger. Single and multiple pipelines make the same trade between simplicity and fit.
Start with the fewest pipelines that meet your real needs. Add a pipeline when you can point to a specific difference in treatment, safety or reliability that a shared one cannot give. Remove a pipeline when its reason disappears.
16Patterns, Anti-patterns and Best Practices
Teams that run many pipelines well share a few habits, and teams that struggle repeat a few mistakes.
Patterns that work
Archive plus analysis
One pipeline keeps a full copy in cheap storage, while another samples and sends to a search or analysis tool.
Redacted outbound pipeline
Anything leaving your network passes through a pipeline that removes sensitive fields first.
Metrics from traces
A connector derives request counts and durations from traces, so you get dependable metrics without extra instrumentation.
Tenant routing
A routing connector sends each team’s data to its own pipeline, backend or account.
Dual shipping for migration
A temporary second exporter or pipeline feeds the new vendor while the old one stays live.
Agent then gateway
Agents do light local work. A gateway does shared, heavy work such as tail sampling.
Anti-patterns to avoid
What it looks like
Every possible combination gets its own pipeline, so the configuration has dozens of near-identical pipelines.
Why it hurts
Memory climbs, changes must be repeated in many places, and nobody can explain the full graph.
Do this instead
Group by real differences in treatment, and use a forward connector for shared steps.
What it looks like
Redaction is placed in the pipeline for the internal archive but forgotten in the pipeline for an outside vendor.
Why it hurts
Private data leaves your control. The mistake is invisible until someone looks at the vendor’s screens.
Do this instead
Make the redaction step mandatory for every pipeline whose exporter sends outside your network, and review it in every change.
What it looks like
Tail sampling is run on several gateway copies without routing spans of one trace to the same copy.
Why it hurts
Each copy sees only part of each trace, so decisions are wrong and sampled traces come out incomplete.
Do this instead
Put a load balancing exporter in front, keyed by trace identity, or use a single tail sampling instance.
What it looks like
A routing connector has rules but no default route.
Why it hurts
Data that matches no rule has nowhere to go and may be silently lost.
Do this instead
Always add a default pipeline that exports to a catch-all destination.
Best practices at a glance
Plan on paper first
Draw a table of pipelines, receivers, processors and exporters before writing any configuration.
Name pipelines by purpose
Use names like traces/archive and logs/audit so a reader understands each pipeline at once.
Memory limiter first, batch late
Apply this order in every pipeline unless you have a clear reason not to.
Validate and test before rollout
Validate the file, run the Collector in a test place with the debug exporter, and send sample data through every pipeline.
Watch input against output
For each pipeline, compare items received with items sent, and alert on unexplained gaps.
Review regularly
Remove pipelines and exporters whose purpose has ended.
When not to add a pipeline
Knowing when to stop is as valuable as knowing how to build. Do not add a pipeline when a single processor could do the job inside an existing one. If two destinations need identical data, two exporters in one pipeline are enough. Do not add a pipeline only because a different team asked for “their own”, if they will receive exactly the same treatment. And do not add a pipeline to hide a design problem, such as a destination that cannot keep up. Fix the destination, or the sampling, rather than building more lines around it.
A useful test is to try to explain the new pipeline in one sentence that names a difference. “This pipeline sends the vendor a copy with customer emails removed” passes the test. “This pipeline is another way to send traces” does not. If you cannot name the difference, you probably do not need the pipeline.
Common mistakes
Assuming two pipelines that use the same processor name share its data. They do not. Each has its own copy, so counts and samples are per pipeline.
Defining a new pipeline but forgetting to list it in the service section. A pipeline that is defined elsewhere but not assembled there will not run.
Putting a component in a pipeline of a signal it does not support, then ignoring the startup error message. Always read the startup output after a change.
17Real-World Walkthrough and Industry Usage
Let us design a multi-pipeline Collector for an imaginary company, then see where the same patterns appear in practice.
ShopFast: one Collector, four goals
ShopFast is an imaginary online store. Its services send traces, metrics and logs to a gateway Collector. The company has four goals. The compliance team wants a full copy of all logs and traces in cheap storage for a year. The engineering team wants traces in a vendor tool, but sampled, because full volume is too costly. The vendor must never receive customer emails or card fragments. And the on-call team wants request-rate and error-rate metrics even for traces that were sampled away.
flowchart LR In["OTLP receiver"] --> TA["traces/archive"] In --> TV["traces/vendor"] In --> TM["traces/metrics"] In --> LA["logs/archive"] In --> LV["logs/vendor"] TA --> Arch["Archive exporter"] LA --> Arch TV --> Vend["Vendor exporter"] LV --> Vend TM --> SM["spanmetrics connector"] SM --> MP["metrics pipeline"] MP --> Vend
Archive pipelines
The traces and logs archive pipelines use only a memory limiter and a batch processor. Both feed the archive exporter, which writes to low-cost storage.
Vendor pipelines
The vendor pipelines add a redaction step that masks emails and card fragments, and the traces one also samples a small share of normal traces while keeping all errors.
A metrics-from-traces pipeline
A separate traces pipeline, with no sampling, feeds the spanmetrics connector. The resulting metrics pass through a metrics pipeline to the vendor, so rates and error counts reflect all traffic.
Check and monitor
The team validates the file, tests each pipeline with sample data, and builds a dashboard comparing items received to items sent per pipeline.
The result is that each goal is met by a pipeline built for it. No application changed. When ShopFast later adds a second vendor for a trial, it adds one exporter and one more pipeline, and removes them when the trial ends.
Where the same patterns appear in industry
Vendor migrations
Companies moving between observability vendors such as Datadog, Grafana Labs, Honeycomb, New Relic, Splunk or Dynatrace commonly send data to both for a period. Because these tools accept OpenTelemetry data, a second exporter or pipeline in the Collector is often enough, with no application change.
Platform teams on Kubernetes
Platform teams often run an agent Collector on every node and a gateway Collector as a central service. The gateway applies shared rules such as redaction, sampling and routing to team-specific backends. This pattern is widely described in the OpenTelemetry documentation.
Open-source backends together
It is common to send traces to Jaeger or Grafana Tempo, metrics to Prometheus-compatible storage and logs to a log store, all from one Collector with one pipeline per signal and destination.
Cloud provider distributions
Cloud providers publish OpenTelemetry Collector distributions that include their own exporters, such as the AWS Distro for OpenTelemetry. Teams combine these with other exporters in extra pipelines, for example to keep a copy outside the cloud.
A second illustrative story: BookNest and regional rules
BookNest is another imaginary company, which sells in several regions. Its legal team requires that customer-related logs from one region never leave that region. The platform team runs one gateway Collector per region, but a central team also wants a small set of safe, anonymised metrics from every region in one global tool.
Regional gateways keep full data local
Each regional gateway has pipelines that send traces and logs only to storage inside its region.
A global pipeline carries only safe data
A separate metrics pipeline, fed by a connector that creates counts from traces, removes all labels that could identify a customer and sends only the counts to the global tool.
Routing handles mixed traffic
In regions that serve several teams, a routing connector sends each team’s data to that team’s storage, with a default pipeline for anything unlabelled.
Audit the design
Reviewers read the pipeline table and confirm that no pipeline connects regional data to a global exporter without removing identifying labels.
The design satisfies the legal rule by construction. A reviewer does not have to inspect individual data items, because the structure of the pipelines shows where each kind of data can go. That ability to reason about data flow from the shape of the configuration is one of the quiet benefits of multiple pipelines.
18Frequently Asked Questions
Short answers to the questions people ask most often.
19Summary and Key Takeaways
If you remember only a handful of ideas from this guide, make it these.
Key Takeaways
- A pipeline is a named path for one signal. It runs from receivers, through processors in order, to exporters, and the Collector can run many at once.
- Naming makes many possible. Add a name after a slash, such as traces/archive, to define several pipelines of the same signal.
- Shared ends, separate middles. Receivers and exporters are shared across pipelines, while each pipeline gets its own processors and therefore its own state.
- Pipelines do not disturb each other. Fan-out gives each pipeline its own copy where needed, so redaction in one never changes another.
- Choose by treatment. Use two exporters in one pipeline for identical copies, and separate pipelines when destinations need different sampling, redaction or isolation.
- Connectors bridge pipelines. They join pipelines, create metrics from traces, route by content, merge shared steps and provide failover, and every routing design needs a default.
- Plan, protect and watch. Put the memory limiter first, set queue limits, redact before data leaves your control, and compare items in with items out for every pipeline.