When to reach for it
- The history of how a thing reached its current state has business value — ledgers, medical records, custody trails, regulated audit
- You need to answer "what did the data look like on the 14th of last month?" without restoring a backup
- Multiple downstream systems care about different aspects of the same change and you'd otherwise wire brittle CDC for each
- You want to fix bugs by replaying into a corrected projection, not by writing one-off migration scripts
- Temporal queries — "show every state this order has been in" — are core to the domain
What it actually costs
You give up UPDATE / DELETE ergonomics. Schema evolution is its own discipline — old events live forever, so you maintain upcasters that translate v1 events into the v3 shape your code expects, possibly for years. Snapshots become essential or every reload is O(history). Ad-hoc 'just check the DB' debugging gets harder. GDPR right-to-erasure against an immutable log has no clean answer — crypto-shredding, tombstones, separate PII stores, pick your poison.
The failure mode nobody mentions
Event design lock-in. The events you wrote on day one become a permanent constraint — every event ever published is part of your domain's vocabulary. A naïve early choice (`UserUpdated` carrying the whole user object) means three years later you're upcasting through six versions on every read, and rethinking the taxonomy means touching every projection. Treat event schemas as a public API from day one.
When not to use it
Your domain doesn't care about history, you don't need audit, and a normal database with a thin audit log does the job — event sourcing is a heavy commitment for benefits nobody is asking for.