Outbox Lifecycle
How durable and hot make state-change events publishable, retryable, and idempotent. A fences each publisher, while the identifies the logical event.
Notes
- State workflows insert durable event records into
outbox_eventsin the same database transaction as the state change. - An insert trigger creates one
outbox_delivery_queuerow for each new event record; this is the hot queue scanned by coordinators. - The publisher claims delivery rows with
available_at <= now()andFOR UPDATE SKIP LOCKED, using the sharded delivery queue index for the hot claim path. - A claim assigns a
claim_token, setsclaimed_until, and moves the delivery rowavailable_atinto the future as a publish lease. - Claimed batches are published with bounded concurrency controlled by the coordinator outbox publish parallelism setting.
- RabbitMQ publication declares durable queues and bindings before publish,
uses persistent ,
sets the outbox
dedupe_keyas the AMQP message ID, publishes with mandatory routing, and waits for a . - Successful publishes mark the ledger event record
publishedand delete the delivery row only when the delivery row still has the sameclaim_token; failed publishes clear the claim and return the delivery row to retry with a delay and error message. - Broker delivery is
.
Exactly-once effects are managed by idempotency guards: outbox
dedupe_key, fenced publisher claims, chunk-claim checks, current-attempt and live-attempt-lease authority checks, and evaluator-result uniqueness.