Expand description
Transactional Outbox — reliable event publishing without dual writes.
§The dual-write problem
“Commit the order, then publish order.created” is two systems with no
shared transaction: crash between them and the database and the event
stream disagree — silently. The outbox pattern closes the gap by writing
the event into an outbox table inside the same database transaction as
the business data, then letting a background relay publish it afterwards
with at-least-once semantics (consumers dedupe on idempotency_key).
§Division of labour
- The app implements
OutboxTx(enqueue inside its DB transaction),OutboxStore(fetch/ack pending rows), andOutboxPublisher(Kafka / NATS / webhook). - The framework ships
with_transaction(begin → work → commit/rollback) andOutboxRelay(background poll-publish-ack loop, spawned fromArclyPlugin::on_start).
Nothing here touches the request hot path beyond the app’s own transaction; the relay is a single background task.
Structs§
- Outbox
Entry - One event enqueued in the same transaction as the business write.
- Outbox
Relay - Background poll → publish → ack loop. At-least-once: an entry is acked
only after a successful publish, so a crash between the two replays it —
consumers must dedupe on
idempotency_key.
Traits§
- Outbox
Publisher - Downstream event transport (Kafka, NATS, webhook fan-out, …).
- Outbox
Store - Committed-but-unpublished entries, fetched/acked by the relay.
- Outbox
Tx - A live database transaction that can also enqueue outbox entries.
- Transactional
Data Source - A datasource that can open outbox-capable transactions.
Functions§
- with_
transaction - Run
workinside one transaction: commit onOk, roll back onErr.