I'm thinking along the lines of redux, where the state is a function of an initial state, and mutations carried out by reducers.
The benefit is that mutations can capture a large amount of information, and as requirements change, the reducers can be modified to produce a new state.
Also, we have a history built in.
Is this a common pattern in database design?
Specifically, I'm considering implementing this on Firestore. What should I know?
Top comments (3)
@rhymes is right. This is event sourcing. We use this in one of our products, and will likely to do so in future products, because our experiences with it are hugely positive. Especially long-term issues like schema changes and historical reports. These are things that can be very painful in current-state-only databases, but are easy with event sourcing.
Instead of each entity being a row in relational DBs or document in doc or KV DBs, each entity has a log (aka stream) of changes. Each individual entry in the log is called an event. (Usually events end up being rows or documents in an event store.) The main operations of an event store are:
Be warned that it does take a little bit more instrumentation to use event sourcing. Events by themselves are not very easy to query. You have to rebuild query data from events. In simple cases, you can do this for every requested query. But particularly listing entities is far too costly to rebuild every time. So you usually end up with 2 databases. An event store for writes and a current-state store for reads. So you need a component that updates the current-state store as new events occur. The nice part about this is that the current-state store is completely disposable. So schema changes are as simple as throwing it away, setting up a new one with different schema, and replaying events onto it.
Design of events is also important. For example, naming an event OrderUpdated is considered an anti-pattern. Because no Order listener is going to know whether they care about that event until they actually open it and examine its data. For maximum usefulness, events should be named with semantic business meaning. For example, OrderCanceled or OrderPaidInFull. Then it should contain the data necessary to process that specific event.
So, there is an up-front investment in knowledge and tooling. But the long-term payoff is high.
You're describing something similar to event sourcing I guess. A system (a DB in your case) in which the state is the result of a series of events applied to the initial state.
If you want to go deeper into event sourcing you might want to take a look at these two posts:
Event Sourcing: What it is and why it's awesome
Barry O Sullivan
A Deconstruction of CQRS
Kasey Speakman
Regarding existing DB designed specifically for that kind of pattern, I only know of EventStore. Note that you can do ES on top of relational DBs as well.
I'm sure there are third party solutions too.
Thanks! Event sourcing is exactly what I was looking for!
It's amazing how easy it is to find relevant reading once you've got the right vocabulary.