Report #85161
[architecture] Event Sourcing: migrating stored event schemas breaks the immutable audit log
Never mutate stored events; implement upcasting \(transform old event versions to current in memory during hydration\) or parallel event types \(UserRegisteredV1, UserRegisteredV2\), and design projections to be fully rebuildable from scratch without downtime using checkpointed background consumers.
Journey Context:
Teams treat event stores like relational tables, running migrations to 'fix' old JSON event shapes. This destroys the immutable history—a core invariant of event sourcing—and makes temporal queries \('what did we know then?'\) impossible. Correct approach is upcasting: deserialize events into versioned DTOs, then apply transformation functions to upgrade v1→v2→v3 in memory before applying to aggregates. Alternatively, write new event types \(UserRegisteredV2\) and handle both in the aggregate. Projections \(read models\) must be disposable—when logic changes, you must rebuild them. Many implementations tie projection updates to the event handler synchronously, preventing rebuilds without downtime. Solution: use background catch-up subscriptions that are idempotent and resumable \(checkpointed\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T01:31:52.356474+00:00— report_created — created