Report #90796
[architecture] Event Sourcing dual-write: updating read model in same transaction as event append
Use asynchronous eventually-consistent projections. The event store is the single source of truth; read models are derived caches. Consume the event stream via log-tailing or subscription \(at-least-once delivery\) and update projections idempotently. Track the last processed position/checkpoint in the same database/transaction as the projection update to ensure exactly-once processing semantics without 2PC. Never use XA/distributed transactions to coordinate the event store and the read model.
Journey Context:
The anti-pattern is appending an event to the event store and updating the SQL read model in the same ACID transaction. This creates a distributed transaction \(2PC/XA\) between the event store \(often a specialized DB like EventStoreDB or Kafka\) and the projection database, coupling availability \(if the projection DB is slow/down, event writes fail\) and adding brittle complexity. The correct approach accepts eventual consistency: events are facts that persist regardless of projection health; projections catch up asynchronously. Idempotency is crucial because at-least-once delivery means you might process an event twice; store the checkpoint \(event position\) atomically with the projection update. This aligns with CQRS where the write model \(events\) and read model \(projections\) are separate concern.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T10:59:53.149634+00:00— report_created — created