SlideShare a Scribd company logo
1 of 54
Download to read offline
CQRS & EVENT SOURCING
IN THE WILD
MICHIEL ROOK
➤ Java, PHP & Scala
developer
➤ Consultant, trainer,
speaker
➤ Dutch Web Alliance
➤ make.io
➤ Maintainer of Phing
➤ @michieltcs
YOU
RAISE YOUR HAND
IF YOU HAVE
heard about CQRS / Event Sourcing
RAISE YOUR HAND
IF YOU HAVE
heard about CQRS / Event Sourcing
followed a tutorial, built a hobby project
RAISE YOUR HAND
IF YOU HAVE
heard about CQRS / Event Sourcing
followed a tutorial, built a hobby project
used it in production
RAISE YOUR HAND
IF YOU HAVE
TOPICS
➤ Quick recap
➤ Replays and rebuilds
➤ Event versioning
➤ Concurrency
➤ Scale
QUICK RECAP
' Event Sourcing ensures that all
changes to application state are stored
as a sequence of events.
-Martin Fowler
ACTIVE RECORD VS. EVENT SOURCING
Account
number
Balance
12345678 €€ 50,00
... ...
Money Withdrawn
Account number 12345678
Amount €€ 50,00
Money Deposited
Account number 12345678
Amount €€ 100,00
Account Created
Account number 12345678
COMMANDS TO EVENTS
Deposit Money
Account number 12345678
Amount €€ 100,00
Money Deposited
Account number 12345678
Amount €€ 100,00
class DepositMoney {

public $accountNumber;

public $amount;

}
class MoneyDeposited {

public $accountNumber;

public $amount;

public $timestamp;

}
function depositMoney(DepositMoney $command) {

$this->apply(new MoneyDeposited($command->accountNumber,

$command->amount, date()));

}
AGGREGATES
class BankAccount {

public $accountNumber;

public $balance;



// command handlers...



public function applyAccountCreated(AccountCreated $event) {

$this->accountNumber = $event->accountNumber;

$this->balance = 0;

}



public function applyMoneyDeposited(MoneyDeposited $event) {

$this->balance += $event->amount;

}



public function applyMoneyWithdrawn(MoneyWithdrawn $event) {

$this->balance -= $event->amount;

}

}
AGGREGATE STATE
Account
number
Balance
12345678 €€ 0,00
Money Withdrawn
Account number 12345678
Amount €€ 50,00
Money Deposited
Account number 12345678
Amount €€ 100,00
Account Created
Account number 56789012
Account
number
Balance
12345678 €€ 100,00
Account
number
Balance
12345678 €€ 50,00
CQRS
➤ Command Query Responsibility Segregation
➤ Separate writes (events) and reads (UI)
➤ Optimize for reads!
Domain
Event Bus
Event Handlers
Command
Repository
Data Layer
Database Database
Event
Store
commands
events
events
queries DTOs
Aggregates
PROS AND CONS
➤ Domain fit
➤ Testing
➤ Audit trail
➤ Scalability
➤ Complexity
➤ Library support / maturity
DISCLAIMER
REPLAYS AND REBUILDS
PROJECTIONS AND READ MODELS
User Registered
User Registered
User Unregistered Number of active users?
PROJECTIONS AND READ MODELS
User Registered
User Deactivated
User Reactivated
Number of active users?
User Registered
User Unregistered
PROJECTIONS AND READ MODELS
User Registered Event Handler
Number of
active users
+1
User Unregistered Event Handler
Number of
active users
-1
PROJECTIONS AND READ MODELS
Events Event Handler(s) Storage
ELASTICSEARCH
class CompanyRegistered {

public $companyId;

public $name;

public $street;

public $city;

}



function handleCompanyRegistered(CompanyRegistered $event) {

$this->elasticsearch->index([

'index' => 'companies',

'type' => 'company',

'id' => $event->companyId,

'body' => [

'name' => $event->name,

'address' => [

'street' => $event->street,

'city' => $event->city

]

]

]);

}
READ MODEL UPDATES
➤ New type
➤ New structure
➤ Based on existing events
➤ Generate from scratch?
REBUILDING
Stop
application
Remove
old read
model
Loop over
events
Apply to
read model
Start
application
ZERO DOWNTIME
Loop over
existing
events
Apply to
new read
model
Apply
queued
events
Start using
new read
model
New events Queue
ELASTICSEARCH: MAPPING CHANGE
Create
index with
new
mapping
Reindex
existing
documents
Apply
queued
events
Start using
new index
New events Queue
CHALLENGE: LONG RUNNING REBUILDS
➤ Alternatives
➤ Distributed
➤ In memory
➤ Partial
➤ Background
CHALLENGE: SIDE EFFECTS
User Registered
User Id 123abc
Email Address test@example.net
Event Handler
Exclude during replays!
CHALLENGE: TRANSACTIONS
Event Handler
Event Handler
Event
Event Handler
Event Handler ?
CHALLENGE: EVENTUAL CONSISTENCY
➤ Asynchronous event handlers
➤ Reads eventually return the same value
➤ Compare with ACID
EVENT VERSIONING
DILEMMA
➤ New business requirements
➤ Refactoring
➤ New view on events
NEW EVENTS / VERSIONS
➤ No longer relevant
➤ Renamed
➤ Additional or renamed field(s)
➤ Too coarse, too fine
SUPPORT YOUR LEGACY?
➤ Events are immutable
➤ Correct (incorrect) old events with new events
UPCASTING
Event Store
UserRegistered_V1
Upcaster
UserRegistered_V2
Event Handler
UPCASTING
class UserRegistered_V1 {

public $userId;

public $name;

public $timestamp;

}



class UserRegistered_V2 {

public $userId;

public $name;

public $date;

}



function upcast($event): array {

if (!$event instanceof UserRegistered_V1) {

return [];

}

return [

new UserRegistered_V2($event->userId, $event->name,

$event->timestamp->format("Y-m-d"))

];

}
REWRITING HISTORY
Load (subset of) events
Deserialize
Modify
Serialize
Save/replace
THINGS TO BE AWARE OF
Upcasting
➤ Performance
➤ Complexity
➤ Existing projections not
automatically updated
Rewriting events
➤ Running code that
depends on old structure
➤ Breaking serialization
➤ Changing wrong events
CONCURRENCY
CONCURRENT COMMANDS
Withdraw Money
Account number 12345678
Amount €€ 50,00
Deposit Money
Account number 12345678
Amount €€ 100,00
?
PESSIMISTIC LOCKING
Withdraw Money
Account number 12345678
Amount €€ 50,00
Deposit Money
Account number 12345678
Amount €€ 100,00
Account
number
Balance
12345678 €€ 100,00
Account
number
Balance
12345678 €€ 50,00
wait for lock
lock
OPTIMISTIC LOCKING
Withdraw Money
Account number 12345678
Amount €€ 50,00
version 1
Deposit Money
Account number 12345678
Amount €€ 100,00
version 1
Account
number
Balance
12345678 €€ 100,00
version 2
ConcurrencyException
SCALE
PERFORMANCE
➤ Server
➤ Database
➤ Framework
➤ Language
STORAGE
➤ #events
➤ #aggregates
➤ #events_per_aggregate
➤ Serializer
➤ Speed
➤ Payload size
➤ Costs
SNAPSHOTS
Events
1 Account Created
2 Money Deposited
3 Money Withdrawn
4 Money Deposited
SNAPSHOT
5 Money Withdrawn
Events
1 Account Created
2 Money Deposited
3 Money Withdrawn
4 Money Deposited
5 Money Withdrawn
SHARDING
➤ Aggregate Id, Type, Event Timestamp, ...
➤ Rebalancing
➤ Distribution
ARCHIVING EVENTS
➤ Reduce working set
➤ Inactive / deleted aggregates
➤ Historic / irrelevant events
➤ Cheaper storage
FRAMEWORK COMPARISON
Framework Upcasting Snapshots Replaying
Broadway
(PHP)
No (PR) No (PR) Not in core
Prooph
(PHP)
MessageFactory
Yes, triggers on
event count
Example code,
off line
Axon
(Java/Scala)
Upcaster /
UpcasterChain
Yes, triggers on
event count
Yes,
ReplayingCluster
Akka
Persistence
(Java/Scala)
Event Adapter
Yes, decided by
actor
Yes
BROADWAY VS PROOPH
class TodoItem extends EventSourcedAggregateRoot {

private $itemId;



public function __construct(PostTodo $command) {

$this->apply(new TodoPosted($command->getItemId()));

}



public function getAggregateRootId()

{

return $this->itemId;

}



public function applyTodoPosted(TodoPosted $event) {

echo "Posted: " . $event->getItemId() . "n";

}

}
BROADWAY VS PROOPH
class TodoItem extends AggregateRoot {

private $itemId;



public function __construct(PostTodo $command) {

$this->recordThat(new TodoPosted($command->getItemId()));

}



protected function aggregateId() {

return $this->itemId;

}



public function whenTodoPosted(TodoPosted $event) {

echo "Posted: " . $event->getItemId() . "n";

}

}
THANK YOU!

More Related Content

What's hot

What's hot (20)

DDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkDDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFramework
 
Event Sourcing with Microservices
Event Sourcing with MicroservicesEvent Sourcing with Microservices
Event Sourcing with Microservices
 
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
 
A practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRSA practical introduction to Event Sourcing and CQRS
A practical introduction to Event Sourcing and CQRS
 
Going Serverless with CQRS on AWS
Going Serverless with CQRS on AWSGoing Serverless with CQRS on AWS
Going Serverless with CQRS on AWS
 
CQRS + Event Sourcing
CQRS + Event SourcingCQRS + Event Sourcing
CQRS + Event Sourcing
 
JavaOne2017: ACID Is So Yesterday: Maintaining Data Consistency with Sagas
JavaOne2017: ACID Is So Yesterday: Maintaining Data Consistency with SagasJavaOne2017: ACID Is So Yesterday: Maintaining Data Consistency with Sagas
JavaOne2017: ACID Is So Yesterday: Maintaining Data Consistency with Sagas
 
Lighning Talk: Event-Driven architecture for microservices
Lighning Talk: Event-Driven architecture for microservicesLighning Talk: Event-Driven architecture for microservices
Lighning Talk: Event-Driven architecture for microservices
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)
 
Event Sourcing - Greg Young
Event Sourcing - Greg YoungEvent Sourcing - Greg Young
Event Sourcing - Greg Young
 
Developing microservices with aggregates (melbourne)
Developing microservices with aggregates (melbourne)Developing microservices with aggregates (melbourne)
Developing microservices with aggregates (melbourne)
 
A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)
 
Event sourcing with Eventuate
Event sourcing with EventuateEvent sourcing with Eventuate
Event sourcing with Eventuate
 
Microservice Architecture with CQRS and Event Sourcing
Microservice Architecture with CQRS and Event SourcingMicroservice Architecture with CQRS and Event Sourcing
Microservice Architecture with CQRS and Event Sourcing
 
Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)
 
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
 
Events, Picos, and Microservices
Events, Picos, and MicroservicesEvents, Picos, and Microservices
Events, Picos, and Microservices
 
Building microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring BootBuilding microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring Boot
 
#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...
 

Similar to CQRS & event sourcing in the wild

Who Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniterWho Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniter
ciconf
 

Similar to CQRS & event sourcing in the wild (20)

CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Kafka as an Event Store - is it Good Enough?
Kafka as an Event Store - is it Good Enough?Kafka as an Event Store - is it Good Enough?
Kafka as an Event Store - is it Good Enough?
 
Kafka as an Event Store (Guido Schmutz, Trivadis) Kafka Summit NYC 2019
Kafka as an Event Store (Guido Schmutz, Trivadis) Kafka Summit NYC 2019Kafka as an Event Store (Guido Schmutz, Trivadis) Kafka Summit NYC 2019
Kafka as an Event Store (Guido Schmutz, Trivadis) Kafka Summit NYC 2019
 
Introduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHPIntroduction to Event Sourcing in PHP
Introduction to Event Sourcing in PHP
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
A Journey with React
A Journey with ReactA Journey with React
A Journey with React
 
FamilySearch Reference Client
FamilySearch Reference ClientFamilySearch Reference Client
FamilySearch Reference Client
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
 
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
 
Kafka as an event store - is it good enough?
Kafka as an event store - is it good enough?Kafka as an event store - is it good enough?
Kafka as an event store - is it good enough?
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
 
How to convert custom plsql to web services-Soap OR Rest
How to convert custom plsql to web services-Soap OR RestHow to convert custom plsql to web services-Soap OR Rest
How to convert custom plsql to web services-Soap OR Rest
 
Who Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniterWho Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniter
 
Patterns for Building Streaming Apps
Patterns for Building Streaming AppsPatterns for Building Streaming Apps
Patterns for Building Streaming Apps
 
CQRS / ES & DDD Demystified
CQRS / ES & DDD DemystifiedCQRS / ES & DDD Demystified
CQRS / ES & DDD Demystified
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
Presentation Paul
Presentation PaulPresentation Paul
Presentation Paul
 

More from Michiel Rook

More from Michiel Rook (7)

The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)
 
The road to continuous deployment (DomCode September 2016)
The road to continuous deployment (DomCode September 2016)The road to continuous deployment (DomCode September 2016)
The road to continuous deployment (DomCode September 2016)
 
The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)
 
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with PhingBuilding and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
 
Building and deploying PHP applications with Phing
Building and deploying PHP applications with PhingBuilding and deploying PHP applications with Phing
Building and deploying PHP applications with Phing
 
Deploying PHP applications with Phing
Deploying PHP applications with PhingDeploying PHP applications with Phing
Deploying PHP applications with Phing
 
Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)
 

Recently uploaded

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 

Recently uploaded (20)

Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 

CQRS & event sourcing in the wild

  • 1. CQRS & EVENT SOURCING IN THE WILD MICHIEL ROOK
  • 2. ➤ Java, PHP & Scala developer ➤ Consultant, trainer, speaker ➤ Dutch Web Alliance ➤ make.io ➤ Maintainer of Phing ➤ @michieltcs
  • 3. YOU
  • 5. heard about CQRS / Event Sourcing RAISE YOUR HAND IF YOU HAVE
  • 6. heard about CQRS / Event Sourcing followed a tutorial, built a hobby project RAISE YOUR HAND IF YOU HAVE
  • 7. heard about CQRS / Event Sourcing followed a tutorial, built a hobby project used it in production RAISE YOUR HAND IF YOU HAVE
  • 8. TOPICS ➤ Quick recap ➤ Replays and rebuilds ➤ Event versioning ➤ Concurrency ➤ Scale
  • 10. ' Event Sourcing ensures that all changes to application state are stored as a sequence of events. -Martin Fowler
  • 11. ACTIVE RECORD VS. EVENT SOURCING Account number Balance 12345678 €€ 50,00 ... ... Money Withdrawn Account number 12345678 Amount €€ 50,00 Money Deposited Account number 12345678 Amount €€ 100,00 Account Created Account number 12345678
  • 12. COMMANDS TO EVENTS Deposit Money Account number 12345678 Amount €€ 100,00 Money Deposited Account number 12345678 Amount €€ 100,00 class DepositMoney {
 public $accountNumber;
 public $amount;
 } class MoneyDeposited {
 public $accountNumber;
 public $amount;
 public $timestamp;
 } function depositMoney(DepositMoney $command) {
 $this->apply(new MoneyDeposited($command->accountNumber,
 $command->amount, date()));
 }
  • 13. AGGREGATES class BankAccount {
 public $accountNumber;
 public $balance;
 
 // command handlers...
 
 public function applyAccountCreated(AccountCreated $event) {
 $this->accountNumber = $event->accountNumber;
 $this->balance = 0;
 }
 
 public function applyMoneyDeposited(MoneyDeposited $event) {
 $this->balance += $event->amount;
 }
 
 public function applyMoneyWithdrawn(MoneyWithdrawn $event) {
 $this->balance -= $event->amount;
 }
 }
  • 14. AGGREGATE STATE Account number Balance 12345678 €€ 0,00 Money Withdrawn Account number 12345678 Amount €€ 50,00 Money Deposited Account number 12345678 Amount €€ 100,00 Account Created Account number 56789012 Account number Balance 12345678 €€ 100,00 Account number Balance 12345678 €€ 50,00
  • 15. CQRS ➤ Command Query Responsibility Segregation ➤ Separate writes (events) and reads (UI) ➤ Optimize for reads!
  • 16. Domain Event Bus Event Handlers Command Repository Data Layer Database Database Event Store commands events events queries DTOs Aggregates
  • 17. PROS AND CONS ➤ Domain fit ➤ Testing ➤ Audit trail ➤ Scalability ➤ Complexity ➤ Library support / maturity
  • 20. PROJECTIONS AND READ MODELS User Registered User Registered User Unregistered Number of active users?
  • 21. PROJECTIONS AND READ MODELS User Registered User Deactivated User Reactivated Number of active users? User Registered User Unregistered
  • 22. PROJECTIONS AND READ MODELS User Registered Event Handler Number of active users +1 User Unregistered Event Handler Number of active users -1
  • 23. PROJECTIONS AND READ MODELS Events Event Handler(s) Storage
  • 24. ELASTICSEARCH class CompanyRegistered {
 public $companyId;
 public $name;
 public $street;
 public $city;
 }
 
 function handleCompanyRegistered(CompanyRegistered $event) {
 $this->elasticsearch->index([
 'index' => 'companies',
 'type' => 'company',
 'id' => $event->companyId,
 'body' => [
 'name' => $event->name,
 'address' => [
 'street' => $event->street,
 'city' => $event->city
 ]
 ]
 ]);
 }
  • 25. READ MODEL UPDATES ➤ New type ➤ New structure ➤ Based on existing events ➤ Generate from scratch?
  • 27. ZERO DOWNTIME Loop over existing events Apply to new read model Apply queued events Start using new read model New events Queue
  • 28. ELASTICSEARCH: MAPPING CHANGE Create index with new mapping Reindex existing documents Apply queued events Start using new index New events Queue
  • 29. CHALLENGE: LONG RUNNING REBUILDS ➤ Alternatives ➤ Distributed ➤ In memory ➤ Partial ➤ Background
  • 30. CHALLENGE: SIDE EFFECTS User Registered User Id 123abc Email Address test@example.net Event Handler Exclude during replays!
  • 31. CHALLENGE: TRANSACTIONS Event Handler Event Handler Event Event Handler Event Handler ?
  • 32. CHALLENGE: EVENTUAL CONSISTENCY ➤ Asynchronous event handlers ➤ Reads eventually return the same value ➤ Compare with ACID
  • 34. DILEMMA ➤ New business requirements ➤ Refactoring ➤ New view on events
  • 35. NEW EVENTS / VERSIONS ➤ No longer relevant ➤ Renamed ➤ Additional or renamed field(s) ➤ Too coarse, too fine
  • 36. SUPPORT YOUR LEGACY? ➤ Events are immutable ➤ Correct (incorrect) old events with new events
  • 38. UPCASTING class UserRegistered_V1 {
 public $userId;
 public $name;
 public $timestamp;
 }
 
 class UserRegistered_V2 {
 public $userId;
 public $name;
 public $date;
 }
 
 function upcast($event): array {
 if (!$event instanceof UserRegistered_V1) {
 return [];
 }
 return [
 new UserRegistered_V2($event->userId, $event->name,
 $event->timestamp->format("Y-m-d"))
 ];
 }
  • 39. REWRITING HISTORY Load (subset of) events Deserialize Modify Serialize Save/replace
  • 40. THINGS TO BE AWARE OF Upcasting ➤ Performance ➤ Complexity ➤ Existing projections not automatically updated Rewriting events ➤ Running code that depends on old structure ➤ Breaking serialization ➤ Changing wrong events
  • 42. CONCURRENT COMMANDS Withdraw Money Account number 12345678 Amount €€ 50,00 Deposit Money Account number 12345678 Amount €€ 100,00 ?
  • 43. PESSIMISTIC LOCKING Withdraw Money Account number 12345678 Amount €€ 50,00 Deposit Money Account number 12345678 Amount €€ 100,00 Account number Balance 12345678 €€ 100,00 Account number Balance 12345678 €€ 50,00 wait for lock lock
  • 44. OPTIMISTIC LOCKING Withdraw Money Account number 12345678 Amount €€ 50,00 version 1 Deposit Money Account number 12345678 Amount €€ 100,00 version 1 Account number Balance 12345678 €€ 100,00 version 2 ConcurrencyException
  • 45. SCALE
  • 46. PERFORMANCE ➤ Server ➤ Database ➤ Framework ➤ Language
  • 47. STORAGE ➤ #events ➤ #aggregates ➤ #events_per_aggregate ➤ Serializer ➤ Speed ➤ Payload size ➤ Costs
  • 48. SNAPSHOTS Events 1 Account Created 2 Money Deposited 3 Money Withdrawn 4 Money Deposited SNAPSHOT 5 Money Withdrawn Events 1 Account Created 2 Money Deposited 3 Money Withdrawn 4 Money Deposited 5 Money Withdrawn
  • 49. SHARDING ➤ Aggregate Id, Type, Event Timestamp, ... ➤ Rebalancing ➤ Distribution
  • 50. ARCHIVING EVENTS ➤ Reduce working set ➤ Inactive / deleted aggregates ➤ Historic / irrelevant events ➤ Cheaper storage
  • 51. FRAMEWORK COMPARISON Framework Upcasting Snapshots Replaying Broadway (PHP) No (PR) No (PR) Not in core Prooph (PHP) MessageFactory Yes, triggers on event count Example code, off line Axon (Java/Scala) Upcaster / UpcasterChain Yes, triggers on event count Yes, ReplayingCluster Akka Persistence (Java/Scala) Event Adapter Yes, decided by actor Yes
  • 52. BROADWAY VS PROOPH class TodoItem extends EventSourcedAggregateRoot {
 private $itemId;
 
 public function __construct(PostTodo $command) {
 $this->apply(new TodoPosted($command->getItemId()));
 }
 
 public function getAggregateRootId()
 {
 return $this->itemId;
 }
 
 public function applyTodoPosted(TodoPosted $event) {
 echo "Posted: " . $event->getItemId() . "n";
 }
 }
  • 53. BROADWAY VS PROOPH class TodoItem extends AggregateRoot {
 private $itemId;
 
 public function __construct(PostTodo $command) {
 $this->recordThat(new TodoPosted($command->getItemId()));
 }
 
 protected function aggregateId() {
 return $this->itemId;
 }
 
 public function whenTodoPosted(TodoPosted $event) {
 echo "Posted: " . $event->getItemId() . "n";
 }
 }