Event sourcing is record storing
Against the grain
I’ve been applying event sourcing (ES) starting from 2018. It has been such a success in my (commercial) projects, that I consider it one of the basic and default pillars in my toolkit. When I decided to give it a try in a serious project, it was after watching only a single video of one of the early presentations by Greg Young. Aside from that, I developed and internalized the idea on my own. More importantly (to me), I was very curious and eager about translating, as an “exercise”, the high-level ideas into a concrete design, which would fit in the Onion architecture and functional programming techniques (e.g. using GADTs for ES APIs).
All this led to me developing my own understanding and a recipe for realization of ES from the “first principles”, not distracted by ideas or approaches of others. To say it less nicely, by the noise-producing hype at the Internet, which usually inevitably arises around such topics and goes on for years.
Much of that seemingly established “canon” is, in my experience, overcomplicated and often misunderstood mess. This applies both to the “theory” and concrete architectural and implementation patterns. From the small conversations online, many people seem to find my approach radical and strange, while I consider the apparently common approach simply “wrong”.
This is the first of my notes about ES. I will summarize my critique first and describe my interpretation and approach in this and multiple future articles.
A summary of my critique
To begin with, there are terms which are very common, but not needed for ES and overcomplicate and obscure it greatly. In no particular order:
- command
- aggregate
- state
- publish
- listeners
- ORM
- entity
- Kafka
- eventual consistency
- CQRS
- event stores
- ES framework
- streams per entity
- closing a stream
- microservices
- …
Secondly, many sources mix up event sourcing (= append-only journal) with data streaming. This is a disastrous mistake to make, both for understanding and practice.
Third, the advice about architecting ES-based applications. Aside from what is implied by the terms above, even the most basic principles of operations are almost always needlessly complex patterns which are very far from the main idea of just folding “events” on demand. Most notably, subscribing to streams and computing view models ahead of time with eventual consistency. This is crazy complexity to me. Then there is the very popular design based on a “decider” and some other fancy sounding and superficially impressing things. We don’t need any of that, it’s all just folding, at the right time.
Lastly, the terminology itself. Up till this point, I’ve been writing “event sourcing”, but this is almost the last paragraph where I do so.
Record storing
I consider “event sourcing” to be a bit of a misnomer, contributing to the overall confusion. What does “event” mean? Sure, it is something which happened, but where? Only in “reality” or also within an application? As an extreme, I had a conversation with someone who firmly believed that whatever happens in the UI, like mouse clicks, are also such events.
As for “sourcing”, maybe it is too subtle for me, but I don’t get it at all. Especially, when event sourcing is, rightfully, compared to bookkeeping. What is “sourced” there and from where? Also, what are even events from reality in bookkeeping? Whoever is familiar with bookkeeping knows, that it is built around very abstract ledgers and transaction between them. Only some, but far from all, transactions have to do with “real” money, accounts and goods.
Therefore, I use and propose the following name:
record storing
I’ve seen some other people start using “record” as well.
The essence of record storing (RS) is that it is a persistence mechanism within an application, where immutable records are stored in the append-only journal. This is in contrast to modifying multiple database tables, files, etc. by replacing older data with newer data. Another crucial difference, is that usually records are more fine-grained than traditional data in, for example, relational database tables.
One reason I like the term “record” is that it subsumes the notion of event. A record may, well, record that something happened. But it can also represent a conclusion or a note made by the application internally, not necessarily corresponding to something literally happening in reality. I guess this is one of the points which “traditional” event sourcing preachers would strongly disagree with.
Going back to data streaming mentioned above, record storing is not a means to decoupling applications or components within an application using reactivity, subscriptions, listeners and such. This can still be done, but is not part of record storing (which is a persistence mechanism!): component A can signal component B that a change happened and B can fold (new) records from the journal by itself. I deliberately don’t specify how that signaling works, but record storing is not a mechanism for that. While this follows “intuitively” from the name, it is not so with “event sourcing”: reacting on events (sourcing?) is very natural and tempting.
Final words
In this piece I am bragging about my supposedly deep insights and even propose a completely new name for a well-known and established idea. I also reject that it is well-known (or at least well-understood) and the way it is established and seemingly promise to explain in more detail how it can be done “better” in future articles.