Over the years I've spoken many times about what Event Sourcing is and shared many of the good, the bad and the ugly parts of it in blog posts and various talks. However, I've never talked about how to actually build a system based on this architecture style. I keep getting the same questions over and over again. Like when to apply Event Sourcing and at what architectural level. How to deal with transactional boundaries within and outside the domain. How to build projections that are autonomous, reliable and self-supporting. How to deal with upgrades and blue-green deployments. But also on how to handle bugs, design mistakes and crashing projections. Having made a lot of these mistakes myself over these years, it's time to share my current thoughts and opinions about this. Since the .NET space has a pretty rich set of open-source projections to support this, the examples and code will be .NET. But the concepts are universal, so don't let that scare you off.
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Event Sourcing from the Trenches (DDD Europe 2020)
1. Dennis Doomen | @ddoomen | Aviva Solutions | The Continuous Improver
2.
3.
4.
5.
6. Command Handlers
Commands
Domain Model
Event Store
Events
App
Query Store
Data Access
Projectors
Events
Query HTTP API
Projections
Events
Command HTTP API
Great unit
of testing
Great unit
of testing
Auditability
comes for free
Can look at
the state in
the past
Can be scaled
independently
Autonomous
projections
Aligns well
with Event
Storming
Forces you to
understand your
domain thoroughly
No relational
table structure
anymore.
Can replay old
data against new
rules
More difficult to
envisage domain
relationships
Great for
replication
7. Application
Command
Service
Correct
Customer
Email Handler
Customer
Unit of
Work
Projector
Data
Access
Layer
Read
Database Write
Database
CorrectCustomerEmailCommand
HTTP API / In-process invocation
Get<Customer>(identity)
Correct Email
Event Store
Load(events)
Apply
Get changes
CustomerEmailCorrectedEvent
Submit changes
History
Dennis Doomen | @ddoomen | The Continuous Improver
NES
Aggregates.NET
SimpleDomain
NStore
EventStore
NEventStore
SQLStreamStore
NStore
NES
Marten
Handelier
Brighter
MediatR (*)
Projac
LiquidProjections (*)
8. Dennis Doomen | @ddoomen | The Continuous Improver
Application
Domain
NoSQL / RDBMS
OR/M / DAL
Web UI, HTTP API,
etc
Lucene Index
Document Projector
Web UI, HTTP
API, etc
Web UI, HTTP API, etc
Domain
Commands
Events
Event StoreProjections
Projectors
Uses Event
Sourcing
Uses traditional
CRUD
architecture
Indexing-based
architecture
Subcribe
to
webhooks
Coarse-
grained
HTTP
requests.
Bus
Subscribe
Publish coarse-
grained event
9. Customer #123
Correct Customer
Shipping Address
Command
Customer Shipping
Address Corrected
Event
Event Store
Treat as a
message, not a
type
Order #456
Correct Shipping Address
Command Handler
Application
Customer Shipping Address
Corrected Handler
Order Redirected
Event.
Identity !=
natural key
Identify
partition key
Primitive types
only
Avoid terms like
Create, Update,
Delete, Change.
Avoid property
change events
Don’t use as
inter-domain
contracts
Don’t expose
outside the
domain
Dennis Doomen | @ddoomen | The Continuous Improver
10. Customer #123
Correct Customer
Shipping Address
Command
Customer Shipping
Address Corrected
Event
Event Store
Order #456
Correct Shipping Address
Command Handler
Application
Order Redirected
Event
Dennis Doomen | @ddoomen | The Continuous Improver
11. Command Service
Some Command
Handler
Customer #123
Event Store
Customer Created
Event
Get<Customer>(“123”)
Customer
Created Event
Converter
Customer Enrolled
Event
May split or
merge events
Can also run as
part of migration
May change the
identity
Unaffected Events
Dennis Doomen | @ddoomen | The Continuous Improver
12. Event
Store
Projector Projector
RDBMS
Subscribe
Subscribe
Document
DB
Projector
RDBMS
Subscribe
Raw SQLNHibernate RavenDB
Lookup
Autonomous &
independent
Storage technique
optimized for
projection
No joining of
projections
Avoid reusing the
projections for
multiple purposes
Use aggressive
caching during
rebuilds.
Caching strategy
optimized for
projector
Owned by
projector
Dennis Doomen | @ddoomen | The Continuous Improver
Stream-by-stream
projections during
rebuilds
17. Event Store
Other Projector
Lookup Projector
Subscription
Subscription
Storage
(persistent)
Lookup
Event
Modifier
Modifies events
with lookup data
Receives
extended events
Dennis Doomen | @ddoomen | The Continuous Improver
18. var stats = new ProjectionStats(() => DateTime.UtcNow);
stats.StoreProperty("CountByDocument", "some setting key", "some value");
stats.LogEvent("CountByDocument", "some significant thing that happened");
stats.TrackProgress("CountByDocument", currentCheckpoint);
float? transactionsPerSecond = stats.GetSpeed("CountByDocument");
TimeSpan? eta = stats.GetTimeToReach("CountByDocument", targetCheckpoint);
public void Configure(IAppBuilder builder)
{
builder.UseStatistics(stats);
}
Dennis Doomen | @ddoomen | The Continuous Improver
20. Document #1
Created Event
Event Store
Graph
Projector
Document #1
Closed Event
(other events)
Projector with
active
projections
Archiving
Projector
Start archiving
Document #1
Marked As
Archivable Event
Mark all events
as archivable
Tracks dependencies
between documents
Deletes
projections
related to
Document #1
Can skip all
archivable events
during next
rebuild.
Dennis Doomen | @ddoomen | The Continuous Improver
21. Event Store
Lucene
Projector
Document #1
Marked As
Archivable Event
Allows projectors
to clean up
Lucene Index
Take snapshot
Purge events
Tombstone
$tombstone
stream
Application
Document
Projector
Search.
Tracks deleted streams
for future references
Stream Tombstoned
Event
Search
Dennis Doomen | @ddoomen | The Continuous Improver
28. • The Good, The Bad and the Ugly of Event
Sourcing
https://www.continuousimprover.com/search/label/event%20sourcing
• Effective Aggregate Design (Vaughn Vernon)
http://dddcommunity.org/library/vernon_2011/
• Liquid Projections
https://www.liquidprojections.net
• Distributed Event Sourcing (Slides)
https://www.slideshare.net/dennisdoomen/building-occasionally-
connected-applications-using-event-sourcing
• Data schema changes in an event sourced
system (paper)
https://files.movereem.nl/2017saner-eventsourcing.pdf