RealWorld Event Sourcing
and CQRS
Matthew Hawkins | @mattchawkins
Agenda
• Overview of my journey into CQRS, ES, and F#
• Explore different patterns, practices and architectures
• 4 Segments
1) Event Sourcing
2) F#
3) Domain Driven Design
4) CQRS
• Disclaimer:This is what I’ve found works (or doesn’t) for us.
• Fast paced, will be covering a lot of information
Traditional Monolithic System
• Concurrency issues (Locking)
• CRUD Design
• Multiple Models
• Lacking developer discipline
• Typically not very scalable
Client
Model-View-Controller
RDBMS
CQRS/DDD/ES System
Client
ReSTful API
Command Model
Consumes
Writes
Query Model
Event
Store
Denormalized
Projection
Publishes
Reads
• Reads/Writes Segregated
• Concurrency Handling
• Clear separation of concerns (Read
vs Domain Model)
• Requires developer discipline
• High-throughput, scalable
Part One
“A way of representing state by storing the
history of the application’s state”
What is Event Sourcing?
What is an Event Store?
An immutable append-only transaction log.
Stock
Traded
Account
Updated
Stock
Traded
Account
Updated
Account
Updated
Time
RDBMS vs ES (Event Sourcing)
Relational Database Event Sourcing
State Current State
Tables Streams
Schemas Buckets
… what is Event Sourcing? (Cont.)
• Event Sourcing is a practice
• Persistence occurs in an “event store”
• Related events compose an “event stream”
• Streams are in chronological order
• Capability to project / rehydrate models
• Majority of RDBMS use a transaction log behind-the-scenes
What is an event?
• Events are state delta’s
• Events are immutable
• Transient or persisted
• Wrapped in a message (Header, Payload)
• Possibly consumed by 3rd parties
• Can be classified as a Domain, Infrastructural or System event
• Most events are past-tense behaviors of the domain (Ex: StockTraded)
What does an event look like?
• Domain Event Example (In F#):
EventVersioning
• Events are persisted in a serialized representation
V1
V2
Event Stream
• Event Stream : Grouping of related events
Stock
Traded
Account
Updated
Stock
Traded
Account
Updated
Account
Updated
Time
100101101 100100 Stream ID
Functionalities of aTransaction Log
• Slice stream
Contiguous subset of the stream
• Probe stream
Returns max score/offset of stream used for concurrency/state version management
• Append stream
Writes to the end of a stream
• Scan stream
Returns a specific subset of the stream (example: scan all “account updated”)
• Get stream
Returns all events from a specific stream, typically used for model rehydration
Rehydration
• The process of querying an event stream (GET) and “applying” it to the
model.
• Allows deterministic rehydration to a given point in time, commonly;
“Current State”
Projections
• Denormalized representation of the model
• Eventually consistent to the write model
• Projections are typically aligned to a specific screen on the UI
• May be organized by Aggregate
Read Model Event Read Model
F#
• F# is a mature, open source, cross-platform, functional-first programming
language.
• Why F#? (With DDD & ES)?
• Self documenting, expressive code
• The type system (algebraic, composable) prevents incorrect state
• Immutable out-of-the-box (Structural equality for value types)
PartTwo
F#Type System Examples
• Comparison
Unit of Measure
RecordType
UnionType
Record withTuples
F# Competitive Advantage
• The code serves as a self-documenting ubiquitous language
• WAY LESS CODE!! Once you learn it
• You can design your domain model to not allow incorrect states at compile
time
• Forced to handle errors (at compile time)
• No nulls! (Alternatives such as Options<‘T> and Choice<‘T1,’T2..>)
Domain Driven Design
• What is DDD?
• When and why DDD?
• What it provides you and your team?
PartThree
Bounded Contexts
• One large model vs. Bounded Contexts
• Can be aligned to an autonomous service
• Can’t start a DDD project without a BC (Bounded Context)
Trading Hedging
Accounting Management
Entities
• Have identity
• Equality is based off identity
• Have behavior associated with them
Values
• No identity
• Immutable
• Structurally equatable
• Explicit type (primitives -> domain concept)
• May have localized behavior
Aggregates
• Abstract notion of
domain types
• Collection of entity
and value types
• Not-concrete
• Load/save aggregates
Aggregate Roots (DDD Context)
• All interaction with the aggregate (entities and values) goes through the
aggregate
• An AR is an Entity
• Manages consistency within the aggregate (all state change)
• Not to be confused with CQRS Aggregate root
Sagas
• Responsible for long-running business processes , “workflows”
• Allows for eventually consistent communication between aggregates
• Consume domain events, fire commands
• Events may be transient
TradeOrderCreated TradeExecuted TransactionRecieved
Command-Query Responsibility
Segregation (CQRS)
• What is CQRS?
• When and why CQRS?
Part Four
System Overview
Client
ReSTful API
Command Model
Consumes
Writes
Query Model
Event
Store
Denormalized
Projection
Publishes
Reads
ReSTful API
HTTPVerb API Action
GET Queries the Read Model
POST Command on Queue -> (Create Command)
PUT Command on Queue -> (Update Command)
DELETE Command on Queue -> (Delete Command)
API Request
API Command
Command Handler
Commands
• Instantiated in the API
• No validation is performed
except for deserialization
• Placed on the queue to go
to the Handler
Triggers
• API Commands are mapped to triggers in the Command Handler
• Triggers are granular domain actions.When fired against the Aggregate
root, yield an event. (Fire : ‘state-> ‘trigger -> ‘event)
• Allow for explicit pathways of state change (Business rules, clear model)
Command Handlers
Aggregate Fire Function
‘state -> ‘trigger -> ‘event
Events
• Domain events represent the delta state change of the model
• The “Fire” function on an Aggregate root yields an event
• Events are serialized and stored in the event store
• Once persisted, they’re broadcasted to interested parties
Event Handlers
• Consume events dispatched from the Event Store
• Commonly used for:
• Updating the Read Model
• Notifying a 3rd party system
• Sagas
CQRS Aggregate Roots
• Gatekeeper for:
• Triggers interacting the with Aggregate
• Model Rehydration (Events)
CQRS Aggregate Root
Sagas,Triggers, and Poly-Aggregate
Communication• Sagas
• Provide an eventually consistent way of communicating between aggregates
• Best used when the process :
• Is “long running” (greater than a few seconds)
• Has a lot of business rules
• Interacts with 3rd party systems
• Trigger Pattern
• Provide a consistent way of multiple aggregates communicating at the same time
• Best used when:
• Two or more aggregates need to be validated/interact atomically
• Triggers are still used with one aggregate at a time!
Projections
• Denormalized representations of the domain model
• Typically correlate to 1) One UI screen 2) An aggregate
• Very similar to domain model rehydration (Apply: ‘state -> ‘event -> ‘state)
• Eventually consistent. Should not be used on the “Command/write side”
• Can be different than the write model
Read Model Query Cache Projection
Event Handlers
Push to ->
API GET->
• geteventstore.com
• NEventStore (++ CommonDomain)
• Domain Driven Design by Eric Evans
• Fsharp.org
• GalaxE Solutions (@GalaxESolutions)
• QuickenLoans (@QLTechnology)
• Matt Hawkins (@MattCHawkins)
Still Interested?

Real World Event Sourcing and CQRS

  • 1.
    RealWorld Event Sourcing andCQRS Matthew Hawkins | @mattchawkins
  • 2.
    Agenda • Overview ofmy journey into CQRS, ES, and F# • Explore different patterns, practices and architectures • 4 Segments 1) Event Sourcing 2) F# 3) Domain Driven Design 4) CQRS • Disclaimer:This is what I’ve found works (or doesn’t) for us. • Fast paced, will be covering a lot of information
  • 3.
    Traditional Monolithic System •Concurrency issues (Locking) • CRUD Design • Multiple Models • Lacking developer discipline • Typically not very scalable Client Model-View-Controller RDBMS
  • 4.
    CQRS/DDD/ES System Client ReSTful API CommandModel Consumes Writes Query Model Event Store Denormalized Projection Publishes Reads • Reads/Writes Segregated • Concurrency Handling • Clear separation of concerns (Read vs Domain Model) • Requires developer discipline • High-throughput, scalable
  • 5.
    Part One “A wayof representing state by storing the history of the application’s state” What is Event Sourcing?
  • 6.
    What is anEvent Store? An immutable append-only transaction log. Stock Traded Account Updated Stock Traded Account Updated Account Updated Time
  • 7.
    RDBMS vs ES(Event Sourcing) Relational Database Event Sourcing State Current State Tables Streams Schemas Buckets
  • 8.
    … what isEvent Sourcing? (Cont.) • Event Sourcing is a practice • Persistence occurs in an “event store” • Related events compose an “event stream” • Streams are in chronological order • Capability to project / rehydrate models • Majority of RDBMS use a transaction log behind-the-scenes
  • 9.
    What is anevent? • Events are state delta’s • Events are immutable • Transient or persisted • Wrapped in a message (Header, Payload) • Possibly consumed by 3rd parties • Can be classified as a Domain, Infrastructural or System event • Most events are past-tense behaviors of the domain (Ex: StockTraded)
  • 10.
    What does anevent look like? • Domain Event Example (In F#):
  • 11.
    EventVersioning • Events arepersisted in a serialized representation V1 V2
  • 12.
    Event Stream • EventStream : Grouping of related events Stock Traded Account Updated Stock Traded Account Updated Account Updated Time 100101101 100100 Stream ID
  • 13.
    Functionalities of aTransactionLog • Slice stream Contiguous subset of the stream • Probe stream Returns max score/offset of stream used for concurrency/state version management • Append stream Writes to the end of a stream • Scan stream Returns a specific subset of the stream (example: scan all “account updated”) • Get stream Returns all events from a specific stream, typically used for model rehydration
  • 14.
    Rehydration • The processof querying an event stream (GET) and “applying” it to the model. • Allows deterministic rehydration to a given point in time, commonly; “Current State”
  • 15.
    Projections • Denormalized representationof the model • Eventually consistent to the write model • Projections are typically aligned to a specific screen on the UI • May be organized by Aggregate Read Model Event Read Model
  • 16.
    F# • F# isa mature, open source, cross-platform, functional-first programming language. • Why F#? (With DDD & ES)? • Self documenting, expressive code • The type system (algebraic, composable) prevents incorrect state • Immutable out-of-the-box (Structural equality for value types) PartTwo
  • 17.
    F#Type System Examples •Comparison Unit of Measure RecordType UnionType Record withTuples
  • 18.
    F# Competitive Advantage •The code serves as a self-documenting ubiquitous language • WAY LESS CODE!! Once you learn it • You can design your domain model to not allow incorrect states at compile time • Forced to handle errors (at compile time) • No nulls! (Alternatives such as Options<‘T> and Choice<‘T1,’T2..>)
  • 19.
    Domain Driven Design •What is DDD? • When and why DDD? • What it provides you and your team? PartThree
  • 20.
    Bounded Contexts • Onelarge model vs. Bounded Contexts • Can be aligned to an autonomous service • Can’t start a DDD project without a BC (Bounded Context) Trading Hedging Accounting Management
  • 21.
    Entities • Have identity •Equality is based off identity • Have behavior associated with them
  • 22.
    Values • No identity •Immutable • Structurally equatable • Explicit type (primitives -> domain concept) • May have localized behavior
  • 23.
    Aggregates • Abstract notionof domain types • Collection of entity and value types • Not-concrete • Load/save aggregates
  • 24.
    Aggregate Roots (DDDContext) • All interaction with the aggregate (entities and values) goes through the aggregate • An AR is an Entity • Manages consistency within the aggregate (all state change) • Not to be confused with CQRS Aggregate root
  • 25.
    Sagas • Responsible forlong-running business processes , “workflows” • Allows for eventually consistent communication between aggregates • Consume domain events, fire commands • Events may be transient TradeOrderCreated TradeExecuted TransactionRecieved
  • 26.
    Command-Query Responsibility Segregation (CQRS) •What is CQRS? • When and why CQRS? Part Four
  • 27.
    System Overview Client ReSTful API CommandModel Consumes Writes Query Model Event Store Denormalized Projection Publishes Reads
  • 28.
    ReSTful API HTTPVerb APIAction GET Queries the Read Model POST Command on Queue -> (Create Command) PUT Command on Queue -> (Update Command) DELETE Command on Queue -> (Delete Command) API Request API Command Command Handler
  • 29.
    Commands • Instantiated inthe API • No validation is performed except for deserialization • Placed on the queue to go to the Handler
  • 30.
    Triggers • API Commandsare mapped to triggers in the Command Handler • Triggers are granular domain actions.When fired against the Aggregate root, yield an event. (Fire : ‘state-> ‘trigger -> ‘event) • Allow for explicit pathways of state change (Business rules, clear model)
  • 31.
  • 32.
    Aggregate Fire Function ‘state-> ‘trigger -> ‘event
  • 33.
    Events • Domain eventsrepresent the delta state change of the model • The “Fire” function on an Aggregate root yields an event • Events are serialized and stored in the event store • Once persisted, they’re broadcasted to interested parties
  • 34.
    Event Handlers • Consumeevents dispatched from the Event Store • Commonly used for: • Updating the Read Model • Notifying a 3rd party system • Sagas
  • 35.
    CQRS Aggregate Roots •Gatekeeper for: • Triggers interacting the with Aggregate • Model Rehydration (Events)
  • 36.
  • 37.
    Sagas,Triggers, and Poly-Aggregate Communication•Sagas • Provide an eventually consistent way of communicating between aggregates • Best used when the process : • Is “long running” (greater than a few seconds) • Has a lot of business rules • Interacts with 3rd party systems • Trigger Pattern • Provide a consistent way of multiple aggregates communicating at the same time • Best used when: • Two or more aggregates need to be validated/interact atomically • Triggers are still used with one aggregate at a time!
  • 38.
    Projections • Denormalized representationsof the domain model • Typically correlate to 1) One UI screen 2) An aggregate • Very similar to domain model rehydration (Apply: ‘state -> ‘event -> ‘state) • Eventually consistent. Should not be used on the “Command/write side” • Can be different than the write model
  • 39.
    Read Model QueryCache Projection Event Handlers Push to -> API GET->
  • 40.
    • geteventstore.com • NEventStore(++ CommonDomain) • Domain Driven Design by Eric Evans • Fsharp.org • GalaxE Solutions (@GalaxESolutions) • QuickenLoans (@QLTechnology) • Matt Hawkins (@MattCHawkins) Still Interested?

Editor's Notes

  • #2 -Welcome to Real World Event Sourcing and CQRS -Matt Hawkins, Consultant @ GalaxE Solutions – primary client Quicken Loans Capital Markets
  • #3 Talk Summary, Agenda, Goal Poll of the Audience Why am I an advocate?
  • #4 -This is Segment 0 -> brief introduction to topics covered so you have context into what I’ll be speaking about -Comparison of Monolithic vs CQRS system -
  • #5 Overview of the architecture Technologies chosen Dive into all areas brifly, tie back to talk plan Talk real world example vs what I’ll be showing
  • #7 Deterministically audit data No-loss biz case
  • #20 -DDD is an approach to software development for complex systems, or where you can gain a competitive advantage from a biz perspective. Invented by Eric Evans Not a silver bullet, a lot is obvious once you read it but it is a learning curve Crafstmanship, focus on the BIZ, -Ubiqitous language Your team: Everyone has a deep focus on the “domain model”, in CQRS, there is one “write model” Everyone speaks the same colloquialisms and language around the domain Designed for evolution and a focus on craftsmanship Final goal : to build better software
  • #21 -What would ordinarily be a very large model, is broken into bounded contexts -Bounded contexts are typically by division/organization/domain focus (different people) -May have different rules or language -Their systems may evolve differently over time -Two bounded contexts may speak the same WORDS but have different meanings -More management from a development perspective
  • #27 Basically separating the reads and writes Pairs well with DDD and ES High throughput/Very fast reads Separtion of responsibility Not a silver bulled
  • #31 PUTs to multiple triggers PATCH this logic may be handled in the API
  • #38 Sagas are a model in themselves, they orchestrate the process and can be more robust than tirggers You
  • #40 Push vs Pull style