Event Sourcing: Projections, Schema Evolution & CQRS
Projections: Fast Reads Without Full Replay
Replaying the full event history on every read request would be prohibitively slow. A projection pre-computes and maintains a ready-to-query view (e.g. 'total orders this month'), updated incrementally as new events arrive -- reads query the fast projection instead of the raw event log.
Event Sourcing + CQRS
Distinct, complementary patterns often paired together -- the natural event stream Event Sourcing produces is an excellent source for building a CQRS read-side projection. Each can be used without the other, since they address genuinely different concerns.
Schema Evolution
# Adding a new required field to a widely-used event type is
# genuinely tricky, since past events can't be retroactively edited
Strategies:
- Version the event type -- handle both old and new schema shapes
in the code that processes/replays events, with sensible defaults
for missing fields on older versions
- "Upcasting" -- transform old-format events into the new format
ON READ, without altering the actual stored historical eventsWhy It Fits Domain-Driven Design
PaymentDeclined { orderId, reason: 'insufficient_funds' } directly captures a meaningful business occurrence in the domain's own language -- more expressive than a raw UPDATE payments SET status = 'declined'. This alignment with genuine domain concepts is a commonly cited reason Event Sourcing pairs naturally with Domain-Driven Design.
When to Reach for Event Sourcing
Domains where the full audit trail is itself valuable (finance, insurance claims, healthcare) -- compliance/auditability comes for free rather than as a bolted-on afterthought.
Ability to reconstruct exact past state supports debugging ('what did this order look like last Tuesday').
Full historical event data supports building new, unanticipated analytics/projections later without having re-instrumented the system in advance.
Best justified by an actual identified need (real audit requirement, real historical-reconstruction use case) rather than adopted speculatively.
Apply selectively -- a financial ledger might benefit while a low-stakes settings feature doesn't need the added complexity.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free