Wat is Event Sourcing?

Event Sourcing is een architectuurpatroon waarbij je niet alleen de huidige staat van data opslaat, maar juist alle gebeurtenissen die tot die staat hebben geleid.

In plaats van alleen op te slaan dat een bestelling bijvoorbeeld PAID is, sla je gebeurtenissen op zoals:

OrderCreated
PaymentStarted
PaymentCompleted

De huidige staat van het systeem ontstaat vervolgens door deze events opnieuw toe te passen.

Voor mij zit de kracht vooral in het feit dat je niet alleen weet wat de huidige situatie is, maar ook waarom het systeem daar terecht is gekomen.

Belangrijke dingen om te weten

Event Sourcing klinkt in eerste instantie vrij logisch, maar het heeft behoorlijk veel invloed op je architectuur.

Je moet bijvoorbeeld goed nadenken over:

  • events die achteraf niet meer gewijzigd mogen worden

  • versionering van events

  • idempotency

  • ordering van events

  • het opnieuw opbouwen van state

  • foutafhandeling

  • eventual consistency

  • observability

Een event is voor mij daarom niet simpelweg een technisch bericht. Het beschrijft iets wat daadwerkelijk binnen het domein is gebeurd.

Daar zit ook direct een belangrijk verschil met normale messaging. Een event als UpdateCustomer vertelt vooral wat een systeem moet doen. CustomerAddressChanged vertelt wat er daadwerkelijk gebeurd is.

Dat onderscheid maakt systemen uiteindelijk veel duidelijker.

Hoe ik naar Event Sourcing kijk

Ik vind Event Sourcing vooral interessant wanneer historie onderdeel is van het domein zelf.

Denk aan financiële processen, orders, betalingen of andere processen waarbij je later exact wilt kunnen reconstrueren waarom een bepaalde status is ontstaan.

Maar ik zou Event Sourcing nooit toepassen omdat een systeem toevallig Kafka gebruikt.

Dat maakt een systeem alleen maar complexer zonder dat je daar automatisch waarde voor terugkrijgt.

Als alleen de huidige staat belangrijk is, dan is een normale database vaak gewoon de betere en vooral simpelere oplossing.

Bewust eenvoudig blijven betekent voor mij ook dat je een patroon niet toepast wanneer het probleem het niet nodig heeft.

Event Sourcing en Eventual Consistency

Event Sourcing sluit natuurlijk sterk aan op Eventual Consistency.

Wanneer verschillende onderdelen van een systeem reageren op events, ontstaat niet overal op hetzelfde moment dezelfde toestand.

Dat hoeft ook niet.

De belangrijkste vraag is welke inconsistentie tijdelijk acceptabel is binnen het domein.

In mijn werk heb ik mij juist veel beziggehouden met Immediate en Eventual Consistency binnen gedistribueerde systemen en microservices. Daarbij heb ik onder andere Kafka, Redis Streams en het Saga-pattern toegepast om processen betrouwbaar over meerdere services heen af te handelen.

Event Sourcing past goed binnen die manier van denken, maar het is geen verplicht onderdeel daarvan.

Hoe ik het gebruik

Wanneer ik Event Sourcing toepas, probeer ik de events zo dicht mogelijk bij de taal van het domein te houden.

Dus liever:

InvoiceCreated
InvoiceSent
PaymentReceived

dan technische gebeurtenissen die alleen beschrijven welke databasehandeling heeft plaatsgevonden.

Daarmee blijven events ook begrijpelijk voor mensen buiten het developmentteam.

Daarnaast vind ik het belangrijk dat consumers zelfstandig met events kunnen omgaan. Een bericht twee keer verwerken mag bijvoorbeeld niet direct betekenen dat dezelfde actie twee keer wordt uitgevoerd.

Daarom horen zaken zoals idempotency, retries en duidelijke foutafhandeling voor mij bij het ontwerp en niet als oplossing achteraf.

Wanneer zou ik Event Sourcing gebruiken?

Ik zou Event Sourcing vooral overwegen wanneer:

  • historie echt onderdeel is van het domein

  • processen gereconstrueerd moeten kunnen worden

  • auditability belangrijk is

  • meerdere modellen uit dezelfde gebeurtenissen opgebouwd moeten worden

  • complexe bedrijfsprocessen uit verschillende stappen bestaan

Wanneer je eigenlijk alleen CRUD nodig hebt, zou ik daar ook gewoon CRUD voor gebruiken.

Een architectuur wordt niet beter doordat er meer patronen in zitten.

De beste architectuur is voor mij meestal degene die het probleem oplost en daarna nog steeds eenvoudig uit te leggen is.

Veelgestelde vragen die ik krijg over Event Sourcing

Gebruik je Event Sourcing altijd bij microservices?

Nee. Microservices en Event Sourcing lossen verschillende problemen op. Ik gebruik Event Sourcing alleen wanneer de historie van het domein daadwerkelijk waarde heeft.

Heb je Kafka nodig voor Event Sourcing?

Nee. Kafka kan uitstekend onderdeel zijn van een event-driven architectuur, maar Event Sourcing gaat voornamelijk over hoe je state opslaat en reconstrueert. Dat zijn twee verschillende verantwoordelijkheden.

Is Event Sourcing hetzelfde als Eventual Consistency?

Nee. Event Sourcing beschrijft hoe state wordt opgebouwd vanuit events. Eventual Consistency beschrijft hoe verschillende delen van een gedistribueerd systeem uiteindelijk dezelfde consistente toestand bereiken.

Wat vind je het moeilijkste aan Event Sourcing?

Niet het opslaan van events, maar wat daarna komt. Event versioning, retries, ordering, idempotency en het corrigeren van fouten bepalen uiteindelijk of de architectuur ook na jaren nog prettig te onderhouden is.

Zou je Event Sourcing aanraden voor een nieuw platform?

Alleen wanneer het domein er aanleiding voor geeft. Ik begin liever simpel en voeg complexiteit toe wanneer het probleem daarom vraagt. Niet andersom.