> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tell.rs/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing

> Route data from any source to any combination of sinks.

Routing controls where your data goes. Each batch from a source is matched against rules you define, and the matched rule determines which sinks receive it. You can send the same data to multiple sinks (fan-out) and attach transforms to specific routes.

## Quick start

The simplest setup sends everything to one sink:

```toml theme={null}
[routing]
default = ["clickhouse"]
```

All data from all sources goes to the ClickHouse sink. No rules needed.

## Adding rules

Rules match data by source and send it to specific sinks. Rules are evaluated top to bottom — the first match wins.

```toml theme={null}
[routing]
default = ["clickhouse"]

[[routing.rules]]
match = { source_type = "syslog" }
sinks = ["clickhouse", "logs"]

[[routing.rules]]
match = { source = "tcp_debug" }
sinks = ["stdout"]
```

In this example:

* Syslog data (both TCP and UDP) goes to ClickHouse **and** the disk sink — fan-out to two destinations
* The debug source goes to stdout only
* Everything else (TCP from SDKs, HTTP) falls through to the default: ClickHouse

## Match conditions

Each rule has a `match` object with one or both of these fields:

| Field         | Matches                                                                                   |
| ------------- | ----------------------------------------------------------------------------------------- |
| `source`      | Exact source name — `"tcp"`, `"tcp_debug"`, `"syslog_tcp"`, `"syslog_udp"`, `"http"`      |
| `source_type` | Source type — `"tcp"` matches all TCP sources, `"syslog"` matches both syslog TCP and UDP |

If you specify both fields, both must match (AND logic).

```toml theme={null}
# Match only the primary TCP source
[[routing.rules]]
match = { source = "tcp" }
sinks = ["clickhouse"]

# Match all syslog sources (tcp + udp)
[[routing.rules]]
match = { source_type = "syslog" }
sinks = ["clickhouse", "logs"]
```

## Evaluation order

1. Rules are checked in the order they appear in the config file
2. The **first matching rule** wins — no further rules are evaluated
3. If no rule matches, data goes to the `default` sinks
4. If no rule matches and `default` is empty, the data is **dropped**

Put specific rules (matching exact source names) before broad rules (matching source types) to avoid early matches swallowing everything.

## Fan-out

A single rule can send data to multiple sinks:

```toml theme={null}
[[routing.rules]]
match = { source_type = "syslog" }
sinks = ["clickhouse", "disk_logs", "forwarder"]
```

Tell delivers to all three sinks without copying the data. If one sink is slow or down, the others still receive their copy — fan-out is independent per sink.

## Adding transforms

Attach transforms to a routing rule to process data before it reaches sinks. Transforms run in order.

```toml theme={null}
[[routing.rules]]
match = { source_type = "syslog" }
sinks = ["clickhouse", "logs"]

[[routing.rules.transformers]]
type = "pattern_matcher"

[[routing.rules.transformers]]
type = "redact"
strategy = "hash"
hash_key = "your-secret"
patterns = ["email", "ipv4"]
```

This extracts log patterns first, then redacts PII, then writes to both sinks. See [Transforms](/pipeline/transforms/overview) for available transform types and their configuration.

## Common patterns

**Analytics + archival:** Send SDK data to ClickHouse for queries and Parquet for long-term storage.

```toml theme={null}
[[routing.rules]]
match = { source = "tcp" }
sinks = ["clickhouse", "archive"]
```

**Separate log handling:** Route syslog through pattern extraction to ClickHouse, while SDK events skip transforms.

```toml theme={null}
[routing]
default = ["clickhouse"]

[[routing.rules]]
match = { source_type = "syslog" }
sinks = ["clickhouse"]

[[routing.rules.transformers]]
type = "pattern_matcher"
```

**Edge forwarding:** Forward all data to a central Tell server.

```toml theme={null}
[routing]
default = ["upstream"]
```
