Sebastian von Conrad - @envato - @vonconrad
UPDATE your VIEW on DELETE
The benefits of Event Sourcing
UPDATE your VIEW on DELETE The benefits of Event Sourcing - - PowerPoint PPT Presentation
UPDATE your VIEW on DELETE The benefits of Event Sourcing Sebastian von Conrad - @envato - @vonconrad Sebastian von Conrad - @envato - @vonconrad Sebastian von Conrad - @envato - @vonconrad Sebastian von Conrad - @envato -
Sebastian von Conrad - @envato - @vonconrad
UPDATE your VIEW on DELETE
The benefits of Event Sourcing
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
In the top 300 of the world’s largest websites.
Sebastian von Conrad - @envato - @vonconrad
Event Sourcing.
Sebastian von Conrad - @envato - @vonconrad
(With an appearance
Sebastian von Conrad - @envato - @vonconrad
What is Event Sourcing?
Sebastian von Conrad - @envato - @vonconrad
What is an Event?
Sebastian von Conrad - @envato - @vonconrad
This poor bugger is horrendously
Sebastian von Conrad - @envato - @vonconrad
An event is a business fact…
Sebastian von Conrad - @envato - @vonconrad
…that happened at a particular time.
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
Event Sourcing, in this context.
Sebastian von Conrad - @envato - @vonconrad
Standard practice is store the current state
database using an ORM.
Sebastian von Conrad - @envato - @vonconrad
When state changes, the DB representation changes.
Sebastian von Conrad - @envato - @vonconrad
John wants to take his partner’s last name.
Sebastian von Conrad - @envato - @vonconrad
ORM
#<User id: 216, first_name: “John”, last_name: “Reed” ...> + --- + ---------- + --------- + --- + | id | first_name | last_name | ... | | --- | ---------- | --------- | --- | | 216 | John | Reed | ... | | ... | ... | ... | ... | + --- + ---------- + --------- + --- +
Sebastian von Conrad - @envato - @vonconrad
ORM
@user.update(last_name: “Hill”) + --- + ---------- + --------- + --- + | id | first_name | last_name | ... | | --- | ---------- | --------- | --- | | 216 | John | Hill | ... | | ... | ... | ... | ... | + --- + ---------- + --------- + --- +
Sebastian von Conrad - @envato - @vonconrad
Event Sourcing doesn’t do that.
Sebastian von Conrad - @envato - @vonconrad
An append-only set
as source of truth.
Sebastian von Conrad - @envato - @vonconrad
Derive everything else from the events.
Sebastian von Conrad - @envato - @vonconrad
Source the current state by replaying events.
Sebastian von Conrad - @envato - @vonconrad
{ user_id: 216, event_type: “signed_up”, body: { first_name: “John”, last_name: “Reed” } } #<User id: 216, first_name: “John”, last_name: “Reed”, ...>
Event Sourcing
Sebastian von Conrad - @envato - @vonconrad
@user.change_name(last_name: “Hill”) { user_id: 216, event_type: “name_changed”, body: { last_name: “Hill” } }
Event Sourcing
Sebastian von Conrad - @envato - @vonconrad
{ event_type: “sign_up”, body: { first_name: “John”, last_name: “Reed” } }, { event_type: “name_changed”, body: { last_name: “Hill” } } #<User id: 216, first_name: “John”, last_name: “Hill”, ...>
Event Sourcing
Sebastian von Conrad - @envato - @vonconrad
Make everything else completely disposable.
Sebastian von Conrad - @envato - @vonconrad
Including current state.
Sebastian von Conrad - @envato - @vonconrad
Language agnostic.
Sebastian von Conrad - @envato - @vonconrad
Why Event Sourcing?
Sebastian von Conrad - @envato - @vonconrad
DELETE is evil.
Sebastian von Conrad - @envato - @vonconrad
Every UPDATE is a DELETE.
Sebastian von Conrad - @envato - @vonconrad
…so UPDATE is evil too.
Sebastian von Conrad - @envato - @vonconrad
Business concepts at the heart of the system.
Sebastian von Conrad - @envato - @vonconrad
It’s tried and tested. (For centuries.)
Sebastian von Conrad - @envato - @vonconrad
You’re using it already and would refuse to do it any
Sebastian von Conrad - @envato - @vonconrad
Current state is hard to distribute.
Sebastian von Conrad - @envato - @vonconrad
Append-only streams
to distribute.
Sebastian von Conrad - @envato - @vonconrad
Last but not least: free time machine!
Sebastian von Conrad - @envato - @vonconrad
CQRS
Sebastian von Conrad - @envato - @vonconrad
CQS: methods can read (queries) or write (commands) but not both.
Sebastian von Conrad - @envato - @vonconrad
CQRS: objects have queries or commands but not both.
Sebastian von Conrad - @envato - @vonconrad
In our world we take it one step further.
Sebastian von Conrad - @envato - @vonconrad
Client Command Handler Query Handler Event Store
Sebastian von Conrad - @envato - @vonconrad
Client Command Handler Query Handler Event Store
Command Event
Sebastian von Conrad - @envato - @vonconrad
Commands represent user intent.
Sebastian von Conrad - @envato - @vonconrad
Commands can be rejected.
Sebastian von Conrad - @envato - @vonconrad
Events are created when commands are accepted.
Sebastian von Conrad - @envato - @vonconrad
Client Command Handler Query Handler Event Store
<= Queries => DTOs Projections
Sebastian von Conrad - @envato - @vonconrad
Projectors process Events in order.
Sebastian von Conrad - @envato - @vonconrad
Projectors maintain denormalised Projections.
Sebastian von Conrad - @envato - @vonconrad
Projectors and Projections are 1:1.
Sebastian von Conrad - @envato - @vonconrad
One Projection per screen/endpoint.
Sebastian von Conrad - @envato - @vonconrad
Query Handlers query projections.
Sebastian von Conrad - @envato - @vonconrad
Query Handlers return DTOs to clients.
Sebastian von Conrad - @envato - @vonconrad
Client Command Handler Query Handler Event Store
<= Queries => DTOs (Sync) Projections (Async) Command (Sync) Event (Sync)
Sebastian von Conrad - @envato - @vonconrad
Eventual Consistency.
Sebastian von Conrad - @envato - @vonconrad
(That thing we’re not supposed to talk about.)
Sebastian von Conrad - @envato - @vonconrad
The world is eventually consistent.
Sebastian von Conrad - @envato - @vonconrad
Is a nanosecond okay? What about a month?
Sebastian von Conrad - @envato - @vonconrad
Risk is always a function of time.
Sebastian von Conrad - @envato - @vonconrad
Downstream Event Processors (aka DEPs).
Sebastian von Conrad - @envato - @vonconrad Client Command Handler Query Handler Event Store
DEPs
Sebastian von Conrad - @envato - @vonconrad Client Command Handler Query Handler Event Store
DEPs
Processes Events Emits Events External Service Triggers Behaviour
Sebastian von Conrad - @envato - @vonconrad
DEPs process events like projectors.
Sebastian von Conrad - @envato - @vonconrad
Can react by emitting events back to the Event stream.
Sebastian von Conrad - @envato - @vonconrad
Can react by triggering external behaviour.
Sebastian von Conrad - @envato - @vonconrad
Encourages clean separation of concerns.
Sebastian von Conrad - @envato - @vonconrad
Case study.
Sebastian von Conrad - @envato - @vonconrad
Country Conflicts.
Sebastian von Conrad - @envato - @vonconrad
Business problem?
Sebastian von Conrad - @envato - @vonconrad
Detect and investigate conflicting information regarding a user’s physical location.
Sebastian von Conrad - @envato - @vonconrad Product A Product B Single Sign-On
Country Conflicts
Evidence Evidence Evidence Product A Product C Conflicts Conflicts
Sebastian von Conrad - @envato - @vonconrad
Gather evidence and store as events.
Sebastian von Conrad - @envato - @vonconrad
DEP looks at evidence and raises ConflictDetected.
Sebastian von Conrad - @envato - @vonconrad
(Another) DEP sees conflict event and emails a notification.
Sebastian von Conrad - @envato - @vonconrad
(Another) DEP might auto-resolve the conflict based on more evidence.
Sebastian von Conrad - @envato - @vonconrad Product A Product B Single Sign-On
Country Conflicts
Evidence Evidence Evidence Product A Product C Conflicts Conflicts Admin UI
Sebastian von Conrad - @envato - @vonconrad
Admins issue Commands to manually resolve conflicts.
Sebastian von Conrad - @envato - @vonconrad
After 30 days, GracePeriodExpired is raised.
Sebastian von Conrad - @envato - @vonconrad
DEP checks whether it is. If not, raises ConflictActivated.
Sebastian von Conrad - @envato - @vonconrad
Sebastian von Conrad - @envato - @vonconrad
Other systems are querying conflicts through projections.
Sebastian von Conrad - @envato - @vonconrad
Small, well-defined, and simple.
Sebastian von Conrad - @envato - @vonconrad
Other systems are substantially larger.
Sebastian von Conrad - @envato - @vonconrad
So why this CQRS architecture?
Sebastian von Conrad - @envato - @vonconrad
Encourages Single Responsibilities.
Sebastian von Conrad - @envato - @vonconrad
Command and Query Handlers can scale independently.
Sebastian von Conrad - @envato - @vonconrad
Writes are fast.
Sebastian von Conrad - @envato - @vonconrad
Reads are faster.
Sebastian von Conrad - @envato - @vonconrad
Projections can be thrown away when no longer needed.
Sebastian von Conrad - @envato - @vonconrad
Separating recording from interpreting what happened.
Sebastian von Conrad - @envato - @vonconrad
Limit blast radius
Sebastian von Conrad - @envato - @vonconrad
Reduces fear and enables rapid change.
Sebastian von Conrad - @envato - @vonconrad
Keep the cost of change lower for longer.
Sebastian von Conrad - @envato - @vonconrad
The heart of a system is far more stable than the edges.
Sebastian von Conrad - @envato - @vonconrad
Should you use it?
Sebastian von Conrad - @envato - @vonconrad
Well, maybe.
Sebastian von Conrad - @envato - @vonconrad
Not appropriate for every problem.
Sebastian von Conrad - @envato - @vonconrad
Works better for read-heavy systems.
Sebastian von Conrad - @envato - @vonconrad
Well suited for commerce-oriented domains, for example.
Sebastian von Conrad - @envato - @vonconrad
Or anywhere where history is important.
Sebastian von Conrad - @envato - @vonconrad
Competitive advantage Complexity
ES? Buy WTF KISS Strategic Design*
Sebastian von Conrad - @envato - @vonconrad
It’s a great tool to have in your toolbox.
Sebastian von Conrad - @envato - @vonconrad
Thank you. Questions?