Storing events in a relational database and creating the event identity as a globally unique and sequentially increasing number is an important and maybe uncommon decision when working with an event-sourced Command Query Responsibility Segregation (CQRS) system Konrad Garus writes in three blog posts describing his experiences from a recent project. In his writing he focuses on how to achieve consistency, how they populate the read models by consuming an event stream and the persistence techniques used in the models.
Garus describes the system as intended for internal use in companies with hundreds or thousands of users and notes it’s relatively low scale, but also that the very simple implementation, although its limited scalability, without problem is capable of handling many hundreds of events per minute.
When using a sequential event identification read models can be updated by regularly polling the event store using the identity of the last already processed event as a starting point, reading a batch of events from the store and processing them in sequence in a single thread. This technique makes the read model responsible for its own state, avoiding any infrastructure or server-side dependencies.
One advantage Garus sees with this model where events are always processed in the order they are created is that although a read model may be behind a few seconds or longer it is always consistent. It’s also possible to calculate how far behind it is by comparing the identity of the last processed event with the current maximum.
Garus also notes that this model makes it possible to mitigate a problem with eventually consistency from a client side perspective. By returning the identity of the last written event created running a command, a client can then use this identity to wait for a read model to be updated reflecting the state after the same event has been processed.
Garus believes that we have a tendency to use tools that are too complex for the actual customer requirements at hand and he thinks their experiences from the described project shows that also when the use of CQRS can be warranted sometimes a simple implementation can solve the problem.
In a discussion at Reddit started after the first blog post it is questioned what value a relational database provide and that the optimal storage is a stream, e.g. an append-only event log. Advantages and disadvantages of Event sourcing instead of a relational model are also raised in the same discussion.
In a blog post late 2014, Vaugh Vernon also proposed using a relational database, PostgreSQL, for storing serialized DDD aggregates, among other things due to its support for ACID transactions and JSON.
Earlier this year Vladimir Khorikov earlier compared three types of CQRS.