Report #66359
[architecture] Writing to database and emitting domain events in the same transaction without the outbox pattern
Write events to a dedicated 'outbox' table in the same ACID transaction as business data; use a separate relay process to poll and publish to the message bus, enabling at-least-once delivery with idempotent consumers.
Journey Context:
The dual write problem: If you commit the DB transaction and then crash before emitting the event, the system is inconsistent. If you emit first and the DB rollbacks, you published a ghost event. The outbox pattern leverages ACID properties: an 'outbox' table \(event\_type, payload, created\_at\) is written in the same transaction as domain changes, guaranteeing atomicity. A separate process \(the relay\) polls this table, publishes to Kafka/SNS, and deletes or marks as processed. The relay must handle at-least-once delivery \(it may crash after publishing but before deleting\), requiring consumers to be idempotent. This is distinct from Change Data Capture \(CDC\) which uses the transaction log; outbox is application-level and allows rich domain events rather than raw DB row changes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T17:51:41.804512+00:00— report_created — created