Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Employing CQRS and Event Sourcing to Build an MVP Beau Simensen • @beausimensen • beau.io joind.in/talk/f87ac
Slide 2
Slide 2 text
What is CQRS?
Slide 3
Slide 3 text
Command / Query Responsibility Segregation
Slide 4
Slide 4 text
No content
Slide 5
Slide 5 text
No content
Slide 6
Slide 6 text
What is Event Sourcing?
Slide 7
Slide 7 text
No content
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
No content
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
No content
Slide 12
Slide 12 text
Why do ES + CQRS?
Slide 13
Slide 13 text
No content
Slide 14
Slide 14 text
What is an MVP?
Slide 15
Slide 15 text
No content
Slide 16
Slide 16 text
Fintech! Accounting + Big Data
Slide 17
Slide 17 text
No content
Slide 18
Slide 18 text
No content
Slide 19
Slide 19 text
MVP Criteria
Slide 20
Slide 20 text
Address Book
Slide 21
Slide 21 text
Deals
Slide 22
Slide 22 text
Solid No rewrites every two years
Slide 23
Slide 23 text
Solid Jump on features quickly
Slide 24
Slide 24 text
Multi-Tenant
Slide 25
Slide 25 text
Single Page Application (SPA)
Slide 26
Slide 26 text
No content
Slide 27
Slide 27 text
React + Redux Flux
Slide 28
Slide 28 text
Material Design Material-UI
Slide 29
Slide 29 text
Internal Framework API + CLI + Container
Slide 30
Slide 30 text
Internal Infrastructure Event Sourcing + CQRS
Slide 31
Slide 31 text
No content
Slide 32
Slide 32 text
Me
Slide 33
Slide 33 text
The Cowboy
Slide 34
Slide 34 text
The Junior
Slide 35
Slide 35 text
(that's it)
Slide 36
Slide 36 text
Testing
Slide 37
Slide 37 text
Modern PHP
Slide 38
Slide 38 text
We built our ES+CQRS Infrastructure as a team
Slide 39
Slide 39 text
No content
Slide 40
Slide 40 text
Choose Boring Technology Dan McKinley http://mcfunley.com/choose-boring-technology
Slide 41
Slide 41 text
"Boring" should not be conflated with "bad." — Dan McKinley
Slide 42
Slide 42 text
... three innovation tokens
Slide 43
Slide 43 text
React 1 Token
Slide 44
Slide 44 text
React for our team? 2 - 3 Tokens
Slide 45
Slide 45 text
Redux 1 Token
Slide 46
Slide 46 text
Redux for our team? 2 - 3 Tokens
Slide 47
Slide 47 text
Material UI 1 Token
Slide 48
Slide 48 text
Material UI for our team? 2 - 3 Tokens
Slide 49
Slide 49 text
Event Sourcing 1 Token
Slide 50
Slide 50 text
Event Sourcing for our team? 2 - 3 Tokens
Slide 51
Slide 51 text
CQRS 1 Token
Slide 52
Slide 52 text
CQRS for our team? 2 - 3 Tokens
Slide 53
Slide 53 text
PSR-7 1 Token
Slide 54
Slide 54 text
PSR-7 for our team? Boring!
Slide 55
Slide 55 text
PHP Boring!
Slide 56
Slide 56 text
MySQL Boring!
Slide 57
Slide 57 text
Envoyer + Forge Boring!
Slide 58
Slide 58 text
Best case? 5 Tokens
Slide 59
Slide 59 text
Worst cases? 10-15 Tokens
Slide 60
Slide 60 text
It took our team SIX MONTHS to reach MVP
Slide 61
Slide 61 text
Similar functionality could have been built in ONE MONTH if we had used Laravel & plain ol' HTML templates
Slide 62
Slide 62 text
We had a solid foundation
Slide 63
Slide 63 text
It felt like a desktop application
Slide 64
Slide 64 text
Six months from MVP we threw in the towel
Slide 65
Slide 65 text
No content
Slide 66
Slide 66 text
Was it the fault of the stack? — me, every day for the next few months
Slide 67
Slide 67 text
Surprise! We're just going to build a CRM. — two weeks after MVP was ready
Slide 68
Slide 68 text
PIVOT
Slide 69
Slide 69 text
Sales and marketing could not sell the product
Slide 70
Slide 70 text
Saturated and Competitive Market
Slide 71
Slide 71 text
Knowing that sooner would have saved us a ton of cash
Slide 72
Slide 72 text
Catch-22
Slide 73
Slide 73 text
If the plan was to just build a CRM I wouldn't have gotten involved.
Slide 74
Slide 74 text
No content
Slide 75
Slide 75 text
Reflection Properties Serializer Optimized for DX
Slide 76
Slide 76 text
Reflection Properties Serializer Started to hurt after 3 months in production...
Slide 77
Slide 77 text
Search Read Model Awesome!
Slide 78
Slide 78 text
History Read Models Neat, but limited...
Slide 79
Slide 79 text
History Read Models Required augmenting events with more info
Slide 80
Slide 80 text
Timeline Full power of Event Sourcing + CQRS
Slide 81
Slide 81 text
Designed for async; never implemented No need to worry about eventual consistency
Slide 82
Slide 82 text
Events change Especially if your domain isn't stable
Slide 83
Slide 83 text
Upcast
Slide 84
Slide 84 text
Version
Slide 85
Slide 85 text
Migration
Slide 86
Slide 86 text
Required downtime for safety
Slide 87
Slide 87 text
Rebuilt all read models from scratch
Slide 88
Slide 88 text
30 seconds For the first month
Slide 89
Slide 89 text
10 minutes By middle of second month
Slide 90
Slide 90 text
Replaying events broke on some changes
Slide 91
Slide 91 text
Rebuilding Read Models (not just when migrating the event stream...)
Slide 92
Slide 92 text
Nuclear Option Rebuild ALL Read Models
Slide 93
Slide 93 text
Rebuilding Individual Read Models Helped a lot with downtime, smaller sets of events
Slide 94
Slide 94 text
Mostly optimized for Read Since write load was generally low...
Slide 95
Slide 95 text
False sense of security Rebuilding Read Models became expensive
Slide 96
Slide 96 text
Rebuilding Read Models while app was active Dangerous!
Slide 97
Slide 97 text
Rebuilding Read Models while app was active Deemed acceptable risk while load was low
Slide 98
Slide 98 text
Rebuilding Read Models while app was active Weird side effects as rebuild started to take longer
Slide 99
Slide 99 text
Solution? Queue events so that new events would not be missed
Slide 100
Slide 100 text
Solution? Replay old events into to new read model repository
Slide 101
Slide 101 text
Solution? Swap new repository for old repository
Slide 102
Slide 102 text
Solution? Start reading events from queue again and start projecting
Slide 103
Slide 103 text
Solution! Follow Store
Slide 104
Slide 104 text
ChatOps
Slide 105
Slide 105 text
Migrations
Slide 106
Slide 106 text
Rebuilding Read Models!
Slide 107
Slide 107 text
Is Read Model up to date?
Slide 108
Slide 108 text
Private State
Slide 109
Slide 109 text
Too strict CQRS led to extra Read Models we probably didn't need...
Slide 110
Slide 110 text
Private State = Private Read Models
Slide 111
Slide 111 text
Eventually moved toward private state for Model
Slide 112
Slide 112 text
Eventually moved toward private state for Read Model
Slide 113
Slide 113 text
Eventually moved toward private state for Services
Slide 114
Slide 114 text
No content
Slide 115
Slide 115 text
Biggest Takeaway? Slower Development.
Slide 116
Slide 116 text
Command -> Command Bus -> Command Handler -> Model -> Events -> Event Store -> Event Bus -> Projector -> Read Model!
Slide 117
Slide 117 text
Adding one new field...
Slide 118
Slide 118 text
Search huge win
Slide 119
Slide 119 text
Timeline huge win
Slide 120
Slide 120 text
Retroactive Features
Slide 121
Slide 121 text
Natural Evolution
Slide 122
Slide 122 text
Event Sourcing makes sense if the Model is known and stable How often is that the case for an MVP?
Slide 123
Slide 123 text
CQRS makes sense if Read Model is not known / flexible Good fit for an MVP!
Slide 124
Slide 124 text
CQRS makes sense if Read Model is not known / flexible At a cost...
Slide 125
Slide 125 text
Can you use an off-the-shelf framework?
Slide 126
Slide 126 text
Event Store
Slide 127
Slide 127 text
Test Harness
Slide 128
Slide 128 text
Good Fit!
Slide 129
Slide 129 text
Rolling an ES+CQRS framework ourself was expensive but was a great investment for the team.
Slide 130
Slide 130 text
Not sure I'd make the same decision today...
Slide 131
Slide 131 text
It DID work though! (But development pace was considerably slower...)
Slide 132
Slide 132 text
Support From Management
Slide 133
Slide 133 text
Had that support initially
Slide 134
Slide 134 text
Unrealistic expectations
Slide 135
Slide 135 text
Eventually just a feature race
Slide 136
Slide 136 text
Eventually just wanted CRUD
Slide 137
Slide 137 text
Pivot changed everything
Slide 138
Slide 138 text
We couldn't sell the MVP This made ES+CQRS infinitely more expensive
Slide 139
Slide 139 text
No content
Slide 140
Slide 140 text
Thanks! @sensiolabs • @thatpodcast Beau Simensen • @beausimensen • beau.io joind.in/talk/f87ac
Slide 141
Slide 141 text
• Stop overthinking…Just stop!