Summary
The outbox pattern eliminates split-brain between a database write and a message broker publish by writing both the domain record and the outbox event in a single ACID transaction, ensuring events are published if and only if the database write committed.
Evidence
- ·Atomic write to both business table and outbox table in one transaction: no window for inconsistency
- ·Outbox relay (Debezium or custom poller) reads committed outbox rows and publishes to Kafka/RabbitMQ
- ·If the relay crashes between read and publish, it restarts and republishes: at-least-once delivery
- ·At-least-once delivery requires idempotent consumers: event_id deduplication in consumer
- ·Debezium's PostgreSQL connector uses WAL-based outbox reading: zero-polling, low latency (~10ms)
Operational Context
- ·Outbox table requires a relay process: this is an additional operational component to monitor
- ·Outbox rows must be cleaned up after relay confirms delivery: unbounded outbox growth causes table bloat
- ·Relay lag (time between commit and publish) should be monitored: sustained lag means event consumers are behind
Tradeoffs
- ·Adds ~1ms write overhead per transaction for the outbox INSERT
- ·Relay is a single point of failure: relay high availability requires careful deployment
- ·At-least-once delivery means consumers must handle duplicate events: idempotency key required
Evidence grounding
Grounded, 5 supporting itemsOutbox pattern is documented by Microservices Patterns (Richardson), DDD community, and production systems at multiple companies as the standard solution for dual-write consistency between a database and a message broker.