Some thoughts on CQRS and Event Sourcing
CQRS and Event Sourcing have had quite a bit of a following among some developers in recent years, especially among the “passionate programmers” in the .NET ecosystem, who have been touting it as a Best Practice. They tell me that it can provide significant benefits when it’s done right, even on small projects.
This may or may not be true. The principles behind CQRS and Event Sourcing look fairly straightforward and the benefits seem clear enough. It does add some extra complexity to your architecture, but it does so in order to solve specific problems. If these are problems that the business is actually asking you to solve, and you’re taking care to keep the extra complexity under control, then you may well be doing CQRS right.
Unfortunately, I’ve more experience with projects that have got CQRS wrong than with ones that have got it right. Some of the worst examples that I’ve seen have been so bad that they made me think of Poe’s Law.
“Without a winking smiley or other blatant display of humour, it is impossible to create a parody of enterprise software best practices that someone won’t mistake for the real thing.”—Poe’s Law, Enterprise Edition™
The principles of CQRS and Event Sourcing may be straightforward enough, but the implementation is a different matter altogether. It’s very easy to end up over-complicating it, and combined with the tendency of many .NET developers to split up their solutions into far more projects and far more layers than necessary, the result can be borderline unmaintainable. I’ve seen one example that required thirty-six files to be edited in order to add a single column to a database table, and another that contained no less than thirty-nine projects in a solution consisting of a single three-page CRUD application that was only ever used by one person once a week.
One sure-fire way of doing CQRS and Event Sourcing wrong is failing to get your entire team on side with it. You may think it’s a better mental model, but the people who are going to maintain it after you need to think the same. This includes not only your domain modelling experts but also your infrastructure and DevOps guys, project managers, and anyone else who is likely to be affected by it. DevOps will want to know how you’re going to handle schema migrations, for example. HR and your project managers will want to know what skills to look for when recruiting, and how to interview for them or provide the necessary training.
I know one project that ended up being completely rewritten because the team of CQRS aficionados who built it failed to put any of this in place. They were all contractors who left without training up any of the organisation’s permanent staff in it. The result was that nobody was able to understand the codebase, let alone maintain it, and it ended up being rewritten from scratch as a conventional BOL/BLL/DAL application. The team who did so now automatically puts any CV they receive that has CQRS listed on it straight into the bin.
Another way of doing it wrong is as an exercise in CV driven development. Some people introduce CQRS and Event Sourcing into a project that they’re working on for no reason whatsoever other than to be able to list it on their CV. Don’t even think of doing this. Besides the fact that it’s stealing from the business, you’ll just end up misunderstanding it, building something that isn’t CQRS, that doesn’t solve the problems that CQRS is supposed to solve, and that over-complicates things without providing any benefit whatsoever. Ideally, you should have at least someone on your team with serious experience supporting and maintaining a legacy CQRS app in production before you try using it on greenfield work, so they can tell you what pitfalls to avoid. Like, for example, when not to use it.
I’ve no doubt that CQRS and Event Sourcing can provide significant benefits when used correctly. However, at the end of the day, any technique, tool or practice will have costs as well as benefits, whether in terms of infrastructure, training, support, maintainability, or general increased complexity. These costs need to be justified by benefits that the business is actually asking for, otherwise you will just be wasting everybody’s time and money.