Operations + evolution (how ES survives contact with time)
The “hard” part of event sourcing is not writing the first version. It’s keeping it healthy after 6 months of change.
1) Event schema evolution
Assume:
- events live forever
- your code changes weekly
Practical rules:
- never “edit history” in production (don’t rewrite old events)
- introduce new event types for breaking changes
- use upcasters for small compatibility upgrades
2) Projection rebuilds (you will do this)
You will rebuild projections when:
- a bug existed in projection logic
- you add a new read model
- you change read model storage
Your system must support:
- rebuild in a separate environment
- cutover to the rebuilt read model
- backfilling + catching up (no missing events)
3) Backpressure and hotspots
Some streams will be “hot” (high write rate). Strategies:
- keep aggregates small (bounded context discipline)
- reduce chatter events (avoid “every click” events)
- snapshot for big streams
- split aggregates if you accidentally modeled a “God aggregate”
4) Observability (non-negotiable)
Minimum signals:
- append failures (wrong expected version)
- projection lag (how far behind is read model)
- outbox queue depth (unpublished count)
- poison event count (events failing deserialization/upcast)
- rebuild duration and throughput
Correlation/causation ids matter:
- correlationId = request trace across services
- causationId = “what caused this event”
5) Security + privacy
Event stores are great audit logs… which means they can also be great liability.
Consider:
- encryption at rest
- field-level encryption for sensitive payloads (depending on store)
- keeping PII out of events (store references, not raw values)
- GDPR “right to be forgotten” strategies (often requires indirection)
No universal answer—this is domain/legal dependent.
6) Deployment and compatibility
Plan for mixed versions:
- old service instances might still write old event schemas
- new instances must read old events
This pushes you toward:
- tolerant readers
- explicit event versioning
- backward compatible serialization
Next
Let’s map these ideas to real .NET tooling: event-native DBs and Orleans.