Why You Should Introduce Event Sourcing and CQRS in Your Company
Developers like to create big database models before they program a single line of code. A carefully designed data model is – so they say – the most important part of the application.
But once you use Event Sourcing, the importance of the structure of the data model vanishes.
Have you ever had a developer saying that a feature XY is not possible, because it wasn't planned for ahead of time? Well, usually what the developer says is the following “To implement feature XY, we need to restructure our database, but because we already have
- a lot of data stored in the database and
- built a lot code that uses that structure,
it will be a hell of a nightmare to implement feature XY or ends up being a big duct tape that ripples through the fabric of space time.
In an Event Sourcing model, the modeling starts with the incoming user events and not with the data model. The data model is a logical consequence of the events and the query requirements of the application. It is not even a “model” anymore, effectively it is just a cached transformation of the events.
The resulting model and its database can – at any time – be recreated by replaying all the events.
So that just eliminated the problem 1 above: In an Event Sourcing model, older events don't need to change. So the old event log just needs to run against a new model that supports the events of the new feature, and tada, you've just got all your data in a new format.
But what about problem 2? What about the code that accesses the database?
Here, CQRS comes into play. When Event Sourcing covers the input to a system, CQRS covers the output of a system.
While you may need to maintain a normalized model of your data, for example to implement undo / redo support, most of your queries shouldn't be done against the model.
Note that the data in our models is not of value anymore, it can be recreated and transformed at will by replaying the events. Moreover, we can create and maintain additional models at any time.
For example, with a CQRS architecture, it is trivial to consistently maintain denormalized database tables that exactly contain all the data that the user is seeing in a particular user interface.
So your query code will automatically, and often for performance reasons, not be programmed against your normalized model, instead it queries nicely prepared denormalized tables.
This effectively simplifies and segregates your user interface queries, and in effect, minimizes the amount of code that needs to be changed.