Skip to main content
Every domain mutation publishes an event. Not to give you a webhook today — to keep the modules that will consume them from wiring into each other directly.

The outbox contract

An event is written in the same transaction as the rows it describes. That single rule buys the guarantee that matters: an event never describes a write that rolled back, and a write that committed never fails to produce its event. Publishing after the commit would make both possible, and both are the kind of bug that surfaces as “the counter is wrong sometimes”. After the commit, the API nudges the queue to drain the outbox. The nudge is best-effort: it buys latency. A periodic sweep is what actually guarantees the outbox drains, even when every nudge is lost.

What is published today

Every event carries the organization it belongs to; customer-plane events carry the environment too.

contact.identified fires once

Only on the actual transition. A second magic link is a sign-in, not a second identification — the SQL that marks the contact identified reports whether it changed anything, and the event is published only when it did.

Payloads carry ids

Ids, not values. Consumers re-read the row, which keeps email addresses and names out of every queue, log and retry buffer the envelope crosses. It also means a consumer that runs late reads the current state rather than a stale copy.

Delivery is at-least-once, and unordered

Two properties that hold today and will still hold when these events become webhooks: the same delivery can arrive twice, and arrival order is not the order of the facts. Every envelope carries a global sequence assigned at commit — that is what orders them, not the clock on arrival.

Outbound webhooks

Not yet. The internal bus is the foundation they will be built on: when outbound webhooks arrive they become one more consumer of the same events, rather than a second publishing path threaded through every handler. Nothing in the list above changes shape when that happens — that is the point of having the bus first.