TechDays 2017 - Event Sourcing after launch how to evolve your event store along with your application

TechDays 2017 - Event Sourcing after launch how to evolve your event store along with your application

Event sourcing can be a solution for certain problems in your application, but it also comes with its own set of challenges.
One of those is the evolution of your event schema. How should you handle changes to events?
We found many approaches while doing our research (we’ve published earlier results in our paper “The Dark Side of Event Sourcing”) and we gained a lot of experienced from building a full-size ERP application using CQRS and event sourcing.
In this talk we will show what kind of approaches we’ve found and what we use to deal with our specific challenges. We will also share early research results from our interviews with over 20 different companies using event sourcing.
Every request for advice can be answered with ‘it depends’, and this talk will not solve that. But we will tell you what your options are, what we think works, and what many others have done.

03dc1d993fa7d5de422c1f35d53f80e6?s=128

Michiel Overeem

October 12, 2017
Tweet

Transcript

  1. 4.
  2. 5.

    accountId balance owner 1234567 0 Michiel Current state Event sourcing

    Event BankAccountCreated (accountId: 1234567, balance: 0, owner: Michiel)
  3. 6.

    accountId balance owner 1234567 100 Michiel Current state Event sourcing

    Event BankAccountCreated (accountId: 1234567, balance: 0, owner: Michiel) DepositPerformed (accountId : 1234567, amount: 100, balance: 100)
  4. 7.

    Event BankAccountCreated (accountId: 1234567, balance: 0, owner: Michiel) DepositPerformed (accountId

    : 1234567, amount: 100, balance: 100) WithdrawalPerformed (accountId: 1234567, amount: 50, balance: 50) accountId balance owner 1234567 50 Michiel Current state Event sourcing
  5. 8.

    Event BankAccountCreated (accountId: 1234567, balance: 0, owner: Michiel) DepositPerformed (accountId

    : 1234567, amount: 100, balance: 100) WithdrawalPerformed (accountId: 1234567, amount: 50, balance: 50) OwnerChanged (accountId: 1234567, newOwner: Marten) accountId balance owner 1234567 50 Marten Current state Event sourcing
  6. 9.
  7. 11.

    Event ShoppingCartCreated (cartid: 1234567, user: Michiel) ArticleAddedToCart(cartid: 1234567, article: Lumia

    950) cartid articles user 1234567 1 Michiel Current state Event sourcing cartid article 1234567 Lumia 950
  8. 12.

    cartid articles user 1234567 0 Michiel Current state Event sourcing

    cartid article Event ShoppingCartCreated (cartid: 1234567, user: Michiel) ArticleAddedToCart(cartid: 1234567, article: Lumia 950) ArticleRemovedFromCart(cartid: 1234567, article: Lumia 950)
  9. 13.

    cartid articles user 1234567 1 Michiel Current state Event sourcing

    cartid article 1234567 iPhone X Event ShoppingCartCreated (cartid: 1234567, user: Michiel) ArticleAddedToCart(cartid: 1234567, article: Lumia 950) ArticleRemovedFromCart(cartid: 1234567, article: Lumia 950) ArticleAddedToCart(cartid: 1234567, article: iPhone X)
  10. 14.

    cartid articles user 1234567 1 Michiel Current state Event sourcing

    cartid article 1234567 iPhone X Event ShoppingCartCreated (cartid: 1234567, user: Michiel) ArticleAddedToCart(cartid: 1234567, article: Lumia 950) ArticleRemovedFromCart(cartid: 1234567, article: Lumia 950) ArticleAddedToCart(cartid: 1234567, article: iPhone X)
  11. 15.
  12. 16.
  13. 17.
  14. 18.
  15. 19.
  16. 20.

    Copyright Nasa Goddard But there is a dark side… How

    can we handle changes? What is the best way for our context?
  17. 22.
  18. 25.
  19. 26.

    Webshop EventStore Customer Stream ShoppingCart Stream CustomerSignedUp { … }

    PriviligeUpgraded { … } ShoppingCartCreated { … } ChangedQuantityOfArticle { … } ArticleAddedToChart { … }
  20. 27.
  21. 31.

    Customer Stream CustomerSignedUp { …, firstName: <string>, surName: <string> }

    PriviligeUpgraded { … } CustomerSignedUp { …, fullName: <string> }
  22. 32.

    Customer Stream CustomerSignedUp { … } PriviligeUpgraded { … }

    OptInOnNewsLetter { … } CustomerSignedUp { …, newsletter: <bool> }
  23. 33.

    Customer Stream CustomerSignedUp { … } PriviligeUpgraded { … }

    OptInOnNewsLetter { … } Customer Stream CustomerSignedUp { … } PriviligeUpgraded { … } NewsletterSubscription Stream OptInOnNewsLetter { … }
  24. 34.

    Store level operations Add / remove streams Merge streams /

    split / … streams Stream level operations Add / remove events Merge events / split / … events Event level operations Add / update / remove attributes Merge attributes / split / … attributes
  25. 35.
  26. 37.
  27. 38.
  28. 39.
  29. 40.
  30. 41.

    Customer Stream CustomerSignedUp { … } PriviligeUpgraded { … }

    CustomerSignedUpV2 { …, newsletter: <bool> }
  31. 46.
  32. 47.
  33. 48.

    Multiple versions Weak schema Upcasters Lazy transformation In place transformation

    Copy and transformation Functional suitability +/- - +/- +/- + +
  34. 49.

    Multiple versions Weak schema Upcasters Lazy transformation In place transformation

    Copy and transformation Maintainability - +/- +/- +/- + +
  35. 50.

    Multiple versions Weak schema Upcasters Lazy transformation In place transformation

    Copy and transformation Performance efficiency + + + +/- +/- -
  36. 52.
  37. 53.
  38. 54.
  39. 55.
  40. 56.
  41. 57.
  42. 58.
  43. 59.
  44. 60.