I am not going to talk about implementing Event Sourcing, pros and cons, or when and where to use it. I want to share my personal developer’s perspective and experience gathered from the two projects I worked on. Both were aiming to develop microservices using domain-driven design principles. The first project (let us call it A) had Event Sourcing and the second one (project B) did not. In both cases, a relational database was required to be used for data persistence.
Project A produced a microservice running in production without major issues. After resolving a few challenges with projection mechanisms, we end up implementing a faithful domain model representing business processes, domain events holding important domain facts and well determined ubiquitous language spoken by the team and the business experts. When the team was assigned to develop microservice B, the same practices were carried over. But then, I realized that it would not go as smoothly as before.
Useless Domain Events
When I first heard Once you get the hang of using Domain Events, you will be addicted and wonder how you survived without them until now, it sounded a bit pretentious and exaggerated, but that is exactly how I have felt since I was introduced to Domain-Driven Design. In my opinion, the greatest power of DDD comes from domain events.
When using event sourcing, everything is spinning around domain events. Working on project A could have been described as talking, thinking, storming, modeling, projecting, storing, trusting and investigating domain events. On the project B, however, we were saving only the latest state of the aggregate and were conveniently deriving the read models from that as well. So, no storing and no domain events needed for projections. To make things worse, there was nothing needed to be subscribed to the domain events the aggregate is publishing. Of course, we decided not to use the concept of domain events, but as a consequence, we had to change the mindset we were used to and continue with a weaker DDD.
Painful refactoring
By gradually expanding domain knowledge, continuous refactoring and adjusting of the domain model were the common practices during development of the microservice A. With event sourcing one can completely remodel the aggregates without having to change anything in the data persisting mechanism. Aggregate properties are just placeholders being filled with data loaded from stored facts — domain events. But when one is storing only the latest state of aggregates, every change drags adjusting database, altering or creating new tables or migrations of existing data. Even though we had created suitable data access objects mapped from the aggregate, changes on the database or in the mappers were inevitable and often time-consuming.
Less focus on the core domain
It did not take long for the team to feel that our focus has moved from the core domain to infrastructure while working on our project B. Even for the slightest change, we were spending too much time, the precious time we used to spend discussing and remodeling the business domain. Not to mention pull requests with more files to review and more code to cover with tests.
Wrapping up
After going through these pain points, I concluded that event sourcing is a natural fit and a powerful supporting tool that strengthens the domain-driven design. Event sourcing brings easier and faster development, testing and debugging. It helps to focus on what is really important — the facts happening in the system shaped as domain events. It facilitates adjusting and continuous improvement of the core domain model. The life of a developer is much easier with event sourcing. But I need to say, it does not mean this should be the primary factor when deciding should a system be event sourced or not. But that is another story for another time.