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

# One Stream, Two Destinations

> Fan out one input to two Destinations and apply a different Transform per Route.

# One Stream, Two Destinations

**Goal:** one incoming event reaches an internal receiver and an external receiver without creating duplicate Streams.

> [!NOTE]
>
> **Screen version:** The numbered images are historical Control UI test captures. Follow the current five-step flow (Connect → Sample & Record Selection → Destinations → Route Processing → Deploy), not older step ordering. See the [numbered screenshot guide](https://control.datarelay.run/use-cases/screen-walkthrough.md).

## When to use this scenario

This scenario builds on an existing Connector, Destination and Stream. If you have not configured a Source yet, start from the [connector-specific collection guides](https://control.datarelay.run/use-cases/index.md). Follow the concrete steps below and verify **actual Logs and Destination/quarantine evidence**. Existing test screenshots are illustrative, not runtime proof.

## 1. Prepare the two receivers

Follow [Lab setup](https://control.datarelay.run/use-cases/lab-setup.md), running independent sinks on ports **9011** and **9012**, each with a separate `received-PORT.ndjson` output file. Use actual reachable test-host addresses.

## 2. Create two Destinations

From **Destinations → Create**:

| Field | Internal | External |
| - | - | - |
| Name | `Lab Internal` | `Lab External` |
| Type | `WEBHOOK_POST` | `WEBHOOK_POST` |
| URL | `http://TEST-HOST:9011/sink` | `http://TEST-HOST:9012/sink` |
| Payload Mode | Single Event Object | Single Event Object |

Save both. Verify the host name or IP is reachable from the Control service.

## 3. Reuse a single Source

Use the Webhook Receiver Connector from [first flow](https://control.datarelay.run/use-cases/webhook-first-flow.md), or create a new one. Open `/streams/new`; finish **Connect** and **Sample & Record Selection** with a confirmed event.

## 4. Add both Destinations to the same Stream

1. Under **Destinations**, select **Lab Internal** and **Lab External**.
2. In **Route Processing**, verify that there are **two separate Routes**.
3. In **Global Processing**, keep common mapping/normalization. The default is to **Inherit Global** settings.
4. Select the Internal Route; leave Transform as **Inherit Global**.
5. Select the External Route; turn **Inherit Global** off for **Transform** only. Add a static output field such as `delivery_scope = external` using the available **Add Field / Static** tool.
6. Inspect the **effective Route preview** for each selected Route. Do not treat a draft Mapping/Enrichment preview as verified Destination delivery.
7. Leave Delivery parameters associated with their own Route; don't expect Delivery settings to be globally inherited.
8. **Deploy** and start the Stream if needed.

![field-mapping — numbered Control historical UI capture](https://mintcdn.com/datarelay-control/Tl9_UibGAprPlCr8/images/screenshots/annotated/field-mapping.webp?fit=max\&auto=format\&n=Tl9_UibGAprPlCr8\&q=85\&s=15ae79d8a5249262f236f997f253d286)

*Figure 1. **Mapping an event to output fields.** ① Inspect the source sample, ② configure Field Mapping, ③ compare Final Event Preview. A preview does not prove real delivery.*

![add-static-field — numbered Control historical UI capture](https://mintcdn.com/datarelay-control/Tl9_UibGAprPlCr8/images/screenshots/annotated/add-static-field.webp?fit=max\&auto=format\&n=Tl9_UibGAprPlCr8\&q=85\&s=d5f7d0d19193036e2aa71d7d4c4a6a62)

*Figure 2. **Adding a custom output field.** ① Select Add field, ② choose Static Value, then ③ close the menu and verify the new field in Final Event Preview.*

## 5. Prove independent fan-out

Send one synthetic JSON event to the generated Webhook Receiver URL:

```bash theme={null}
curl --fail-with-body -X POST "$CONTROL_RECEIVER_URL" \
  -H 'Content-Type: application/json' \
  --data '{"id":"two-route-001","message":"fanout check","severity":"low"}'
```

Check `received-9011.ndjson` and `received-9012.ndjson`; correlate **the same input ID** with two Route-specific Logs entries. Verify `delivery_scope` appears **only** where the effective external Transform supports it.

**PASS =** two destination receipts, one Stream, two distinct Route outcomes. If one Route fails, record the per-Route result rather than treating the whole event as fully delivered.

## If it fails

* **Only one receipt:** recheck both Destinations and Routes are enabled and tied to the Stream.
* **Identical payloads when expecting differences:** verify the override was saved, not merely staged or shown in a preview.
* **Deploy says Intent only / a Route reports Inherited:** open **Routes → Edit**, save the complete supported override, then check Effective Status for **Overridden**.
* **A second Stream was created for the other sink:** that is not required; consolidate the destinations under one Stream.

**Next:** [mask sensitive fields on one Route](https://control.datarelay.run/use-cases/protect-pii.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.