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

# Event streaming overview

> Shared event streaming contract for Lerian products — the CloudEvents envelope, topic and type conventions, schema versioning, and delivery guarantees.

Lerian products emit domain events — past-tense business facts such as an account being created or a credential being issued — onto a shared streaming backbone. Any service or downstream subscriber consumes them without coupling to the producer's internal APIs. This page describes the wire contract every event on the platform follows. The per-product pages list the concrete events each system emits and consumes. [Streaming Hub](/en/streaming-hub/what-is-streaming-hub) delivers these same events to your own infrastructure — webhooks, SQS, RabbitMQ, EventBridge, or pull — with managed retries.

## Transport

Events travel as **CloudEvents 1.0** messages in **binary content mode**. Binary mode puts the CloudEvents context attributes in transport headers, each prefixed with `ce-`, and the event body in the message value as JSON. A consumer reads routing and identity from the headers without deserializing the payload.

Most producers — Midaz, Tracer, Lender, Matcher, Consignado — publish over **Kafka**. Two publish the same envelope over **RabbitMQ**: [Reporter](/en/reference/events/reporter) routes each event to a configured exchange with the event key as the routing key, and [Fetcher](/en/reference/events/fetcher) does the same for its job terminal events. The envelope, typing, versioning, and delivery semantics below apply identically on both transports.

## The envelope

Every record carries these CloudEvents headers.

| Header               | Present  | Carries                                              |
| -------------------- | -------- | ---------------------------------------------------- |
| `ce-specversion`     | Always   | CloudEvents spec version — `1.0`.                    |
| `ce-id`              | Always   | Unique event id (UUIDv7). Deduplicate on this value. |
| `ce-source`          | Always   | The producing service.                               |
| `ce-type`            | Always   | Event type — `studio.lerian.<resource>.<event>`.     |
| `ce-time`            | Always   | Emission timestamp (RFC 3339).                       |
| `ce-resourcetype`    | Always   | The resource — for example `account`.                |
| `ce-eventtype`       | Always   | The event — for example `created`.                   |
| `ce-schemaversion`   | Always   | Payload schema version.                              |
| `ce-subject`         | When set | The aggregate id the event concerns.                 |
| `ce-tenantid`        | When set | The owning tenant; omitted for single-tenant scope.  |
| `ce-datacontenttype` | When set | Body media type — `application/json`.                |

## Event type

The `ce-type` header names the event as `studio.lerian.<resource>.<event>`. An account creation in the ledger is `studio.lerian.account.created`. The two segments also appear on their own in `ce-resourcetype` and `ce-eventtype`, so a consumer filters on either the full type or its parts.

## Topic naming

Kafka topic names are **not shared across producers** — there is no single platform-wide prefix. Each producer owns its own topic namespace, and a name follows one of two patterns depending on how the producer routes its events. The per-product pages list the exact topic for every event; the rules below let you predict the shape and know which producer a record came from.

### Explicit topics (Midaz)

Midaz routes each event to an explicit destination it owns:

* The **ledger core** publishes under `lerian.streaming.ledger_<resource>.<event>`.
* The **CRM and Fees capabilities** — emitted by the same consolidated ledger service, sharing its `ce-source` — keep their own segments: `lerian.streaming.crm_<resource>.<event>` and `lerian.streaming.fee_<resource>.<event>`.
* **Tracer** publishes under `lerian.streaming.tracer_<resource>.<event>`.

Midaz normalizes hyphens to underscores in the topic tail so every segment matches `[a-z0-9_]`: `balance.config-changed` lands on `lerian.streaming.ledger_balance.config_changed`, while its `ce-type` keeps the hyphen (`studio.lerian.balance.config-changed`). The topic tail is the only place the underscore form appears — the event identity carried in `ce-type`, `ce-resourcetype`, and `ce-eventtype` is unchanged.

### Source-derived topics (Lender, Matcher, Consignado, cross-product commands)

Other producers derive the topic from their CloudEvents source:

```
<ce-source>.<resource>.<event>
```

Lender emits under `lender.<resource>.<event>`, Matcher under `matcher.<resource>.<event>`, and Consignado under `consignado-gw.<resource>.<event>`. A command one product sends to another keeps the **producer's** namespace, not the consumer's — a command Consignado consumes from Lender arrives on `lender.<resource>.<event>`. The source segment is lowercased and any character outside `[a-z0-9._-]` is folded to a hyphen before it is used, so pick a source value that stays unique after that normalization.

A derived topic carries no version suffix for a `1.x` schema; a **major** schema bump (`2.0.0` and above) appends `.v<major>` to the topic — for example `...event.v2` — so a breaking payload change moves consumers to a new topic instead of reinterpreting the old one. Midaz's explicit topics are fixed literals and never carry a version suffix — a breaking schema change on an explicit topic is signalled only by `ce-schemaversion`, not by the topic name.

## Source

`ce-source` identifies the producing service. It is **deployment-configured** through the `STREAMING_CLOUDEVENTS_SOURCE` environment variable. The ledger (including CRM and Fees), Consignado, Matcher, Reporter, and Fetcher **require** it: with streaming enabled, they fail to boot when it is unset rather than emitting under a guessed source. Lender goes further and enforces the exact value `lender`. Tracer instead ships an in-code default (`lerian.midaz.tracer`) and treats the variable as an override. Set a stable, descriptive value per deployment.

`ce-source` records where a record originated, for auditing and consumer-side routing. For producers that derive their topics from it (see [Topic naming](#topic-naming)), the source also determines the topic namespace, so its value is part of the wire contract, not just metadata. Midaz routes to explicit topics instead, so its source appears on `ce-source` for attribution but does not shape the topic name.

## Subject and tenant

`ce-subject` carries the id of the aggregate the event is about — the account, transaction, or credential the fact concerns. `ce-tenantid` carries the owning tenant in multi-tenant deployments; it is omitted for single-tenant business events, so a consumer treats an absent tenant id as valid single-tenant scope rather than an error.

## Schema versioning

Each event declares its own payload schema version in `ce-schemaversion`, independent of other events on the same source. The default is `1.0.0`. A minor bump is additive and backward compatible; a major bump is a breaking change. The version lives in the header, never in the topic name, so a consumer that reads payloads as a [tolerant reader](/en/reference/tolerant-reader) — ignoring unknown fields — is unaffected by an additive change.

## Delivery guarantees

Delivery is **at-least-once**. A consumer commits its position only after it finishes handling a record, so a crash mid-handling replays the record rather than dropping it — which means the same event can arrive more than once. Deduplicate on `ce-id` and keep handlers idempotent.

On the producer side, the delivery policy belongs to each event definition, not to the platform. A product that declares an event **outbox-backed** writes it to its outbox in the same database transaction as the state change that produced it. The event and the fact it reports commit or roll back together. A relay then publishes committed outbox rows to the producer's transport (Kafka or RabbitMQ) and retries through broker outages. Lender, Consignado, and Fetcher declare every event in their catalogs this way; Matcher and Reporter split their catalogs — audit-grade facts are outbox-backed, operational signals publish directly with an outbox fallback. Read the product's own event page for the policy its catalog carries, and where the product exposes a streaming manifest, read the manifest at startup.

## Per-product catalogs

| Producer                  | Page                                                 | Transport | Streaming manifest                                                        |
| ------------------------- | ---------------------------------------------------- | --------- | ------------------------------------------------------------------------- |
| Midaz (ledger, CRM, Fees) | [Midaz events](/en/reference/events/midaz)           | Kafka     | —                                                                         |
| Tracer                    | [Tracer events](/en/reference/events/tracer)         | Kafka     | —                                                                         |
| Lender                    | [Lender events](/en/reference/events/lender)         | Kafka     | `GET /api/v1/streaming/manifest`                                          |
| Matcher                   | [Matcher events](/en/reference/events/matcher)       | Kafka     | `GET /system/matcher/streaming/manifest`                                  |
| Consignado                | [Consignado events](/en/reference/events/consignado) | Kafka     | —                                                                         |
| Reporter                  | [Reporter events](/en/reference/events/reporter)     | RabbitMQ  | [`GET /v1/streaming/events`](/en/reference/reporter/get-streaming-events) |
| Fetcher                   | [Fetcher events](/en/reference/events/fetcher)       | RabbitMQ  | —                                                                         |

The Brazil rails (STA, CCS, SLC, SPB, SPI, SILOC, SISBAJUD, bank transfer, and the Pix services) also publish events on this same contract; see each rail's own documentation area for its catalog.
