Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Employing CQRS and Event Sourcing to Build an MVP (Sunshine PHP 2017)

Employing CQRS and Event Sourcing to Build an MVP (Sunshine PHP 2017)

Learning about Command Query Responsibility Segregation (CQRS) and Event Sourcing can be both exciting and confusing. It sounds great, but how does it work in the real world? Won't it be a lot of work before you even get started? Will it be worth the investment and when will that investment start paying off? Are these technologies appropriate for building a minimum viable product (MVP)? Find out how these questions were answered for one team as they set out to build their MVP.

Beau Simensen

February 04, 2017

More Decks by Beau Simensen

Other Decks in Programming


  1. Employing CQRS and Event Sourcing to Build an MVP Beau

    Simensen • @beausimensen • beau.io joind.in/talk/f87ac
  2. What is CQRS?

  3. Command / Query Responsibility Segregation

  4. None
  5. None
  6. What is Event Sourcing?

  7. None
  8. None
  9. None
  10. None
  11. None
  12. Why do ES + CQRS?

  13. None
  14. What is an MVP?

  15. None
  16. Fintech! Accounting + Big Data

  17. None
  18. None
  19. MVP Criteria

  20. Address Book

  21. Deals

  22. Solid No rewrites every two years

  23. Solid Jump on features quickly

  24. Multi-Tenant

  25. Single Page Application (SPA)

  26. None
  27. React + Redux Flux

  28. Material Design Material-UI

  29. Internal Framework API + CLI + Container

  30. Internal Infrastructure Event Sourcing + CQRS

  31. None
  32. Me

  33. The Cowboy

  34. The Junior

  35. (that's it)

  36. Testing

  37. Modern PHP

  38. We built our ES+CQRS Infrastructure as a team

  39. None
  40. Choose Boring Technology Dan McKinley http://mcfunley.com/choose-boring-technology

  41. "Boring" should not be conflated with "bad." — Dan McKinley

  42. ... three innovation tokens

  43. React 1 Token

  44. React for our team? 2 - 3 Tokens

  45. Redux 1 Token

  46. Redux for our team? 2 - 3 Tokens

  47. Material UI 1 Token

  48. Material UI for our team? 2 - 3 Tokens

  49. Event Sourcing 1 Token

  50. Event Sourcing for our team? 2 - 3 Tokens

  51. CQRS 1 Token

  52. CQRS for our team? 2 - 3 Tokens

  53. PSR-7 1 Token

  54. PSR-7 for our team? Boring!

  55. PHP Boring!

  56. MySQL Boring!

  57. Envoyer + Forge Boring!

  58. Best case? 5 Tokens

  59. Worst cases? 10-15 Tokens

  60. It took our team SIX MONTHS to reach MVP

  61. Similar functionality could have been built in ONE MONTH if

    we had used Laravel & plain ol' HTML templates
  62. We had a solid foundation

  63. It felt like a desktop application

  64. Six months from MVP we threw in the towel

  65. None
  66. Was it the fault of the stack? — me, every

    day for the next few months
  67. Surprise! We're just going to build a CRM. — two

    weeks after MVP was ready
  68. PIVOT

  69. Sales and marketing could not sell the product

  70. Saturated and Competitive Market

  71. Knowing that sooner would have saved us a ton of

  72. Catch-22

  73. If the plan was to just build a CRM I

    wouldn't have gotten involved.
  74. None
  75. Reflection Properties Serializer Optimized for DX

  76. Reflection Properties Serializer Started to hurt after 3 months in

  77. Search Read Model Awesome!

  78. History Read Models Neat, but limited...

  79. History Read Models Required augmenting events with more info

  80. Timeline Full power of Event Sourcing + CQRS

  81. Designed for async; never implemented No need to worry about

    eventual consistency
  82. Events change Especially if your domain isn't stable

  83. Upcast

  84. Version

  85. Migration

  86. Required downtime for safety

  87. Rebuilt all read models from scratch

  88. 30 seconds For the first month

  89. 10 minutes By middle of second month

  90. Replaying events broke on some changes

  91. Rebuilding Read Models (not just when migrating the event stream...)

  92. Nuclear Option Rebuild ALL Read Models

  93. Rebuilding Individual Read Models Helped a lot with downtime, smaller

    sets of events
  94. Mostly optimized for Read Since write load was generally low...

  95. False sense of security Rebuilding Read Models became expensive

  96. Rebuilding Read Models while app was active Dangerous!

  97. Rebuilding Read Models while app was active Deemed acceptable risk

    while load was low
  98. Rebuilding Read Models while app was active Weird side effects

    as rebuild started to take longer
  99. Solution? Queue events so that new events would not be

  100. Solution? Replay old events into to new read model repository

  101. Solution? Swap new repository for old repository

  102. Solution? Start reading events from queue again and start projecting

  103. Solution! Follow Store

  104. ChatOps

  105. Migrations

  106. Rebuilding Read Models!

  107. Is Read Model up to date?

  108. Private State

  109. Too strict CQRS led to extra Read Models we probably

    didn't need...
  110. Private State = Private Read Models

  111. Eventually moved toward private state for Model

  112. Eventually moved toward private state for Read Model

  113. Eventually moved toward private state for Services

  114. None
  115. Biggest Takeaway? Slower Development.

  116. Command -> Command Bus -> Command Handler -> Model ->

    Events -> Event Store -> Event Bus -> Projector -> Read Model!
  117. Adding one new field...

  118. Search huge win

  119. Timeline huge win

  120. Retroactive Features

  121. Natural Evolution

  122. Event Sourcing makes sense if the Model is known and

    stable How often is that the case for an MVP?
  123. CQRS makes sense if Read Model is not known /

    flexible Good fit for an MVP!
  124. CQRS makes sense if Read Model is not known /

    flexible At a cost...
  125. Can you use an off-the-shelf framework?

  126. Event Store

  127. Test Harness

  128. Good Fit!

  129. Rolling an ES+CQRS framework ourself was expensive but was a

    great investment for the team.
  130. Not sure I'd make the same decision today...

  131. It DID work though! (But development pace was considerably slower...)

  132. Support From Management

  133. Had that support initially

  134. Unrealistic expectations

  135. Eventually just a feature race

  136. Eventually just wanted CRUD

  137. Pivot changed everything

  138. We couldn't sell the MVP This made ES+CQRS infinitely more

  139. None
  140. Thanks! @sensiolabs • @thatpodcast Beau Simensen • @beausimensen • beau.io

  141. • Stop overthinking…Just stop!