Just another example of CQRS and ES

 Maybe you have heard about CQRS (Command Query Responsibility Segregation) design pattern together with ES (Event Sourcing) pattern so many times.

However, you may still confuse about it and I am here to give to you an example and also some personal feedback / view about it. (Yes, I am usually very critical instead of hype easily with new patterns, architectures or languages).

Before I start defining a bit CQRS - ES I prefer to share the GitHub repository and some instructions first.

You can find here https://github.com/DanielMerchan/cqrs-es-java-spring-plain a CQRS example with instructions to make it working

  • There are two branches:
    • initial: It is the skeleton project if you want to build it yourself by following every <Step>.md of the main branch
    • main: Contains the CQRS example. Take into consideration the following
      • Make sure 0.md is done in your machine and you have docker ready with the services running
      • 14.md and 20.md has examples on how to test the application
  • All the .md have a lot of information.
  • I recommend to execute the programs in debug mode and slowly move around the code for understanding.

CQRS

CQRS stands for Command Query Responsibility Segregation) which consists basically into separating the Command model (writes) from the Query model (reads)

Traditional vs CQRS


What are exactly Commands and Queries?
  • Command: They are instructions to perform an action that changes the state of the application. They represent intent and are typically initiated by the user or an external system.
  • Query: They are requests to retrieve data from the system. They do not alter the state of the application but rather fetch and return the required information.
The first question that comes to your mind maybe is... Why are we doing this?

Benefits of CQRS

As every new pattern, architecture style there are benefits about it. 
  • The separation of each model allows to each own to be independently optimised. 
  • By isolating these concerns, this can lead to more efficient resource utilisation and evolution of complex systems.
Yes, bla bla bla above... Let's go to human language
  • There are too many data stores, databases etc... which are optimal for massive write, or high performant query. It is important to select the appropiate data store for Command and for Query. Example could be to write into MongoDB and to read from Elastic Search for example.
  • CQRS already enforces somehow to drive the solution with an event driven / asynchronous architecture which are "so fancy" nowadays and gets you ready for ensuring delivering the best scalable and performance.

Amazing right? But for a second, let's put or feet on the ground again and talk about what are the cons of using CQRS. It is not easy at all to implement and comes with a cost implication.

Careful... CQRS brings also not good things

I am tired of repeating myself everyday that every new pattern, architecture style does not mean it replaces old ones. It is another one to consider for your specific use case. 
What to consider about CQRS?
  • The obvious one is Complexity. Separating the read/write models into two microservices already implies and increase of complexity and the need for adding new data stores and somehow a communication system between those like Kafka, RabbitMQ, JMS or pigeon as a service (joke).
  • Eventual Consistency!!!. Probably this is the most painful word about event driven asynchronous architectures, microservices and the nowadays world. Basically, when you write a transaction it will be a delay for the read microservice to replicate the data and make it available for the consumers. You will need to think on mechanisms to notify when data is ready for your UIs or other systems (callbacks).
  • Learning curve: If you try also to apply DDD (domain driven design) and CQRS together you may notice you require some skill to implement it properly (even the example I am sharing later has flaws, but it works)
  • Costs. Yeah, prepare your wallet. Instead a  mono/modu-lith deployed in a single compute instance and making your life easier. Now you have 2 microservices in containers, deployed in an amazing Kubernetes cluster, communicated via Kakfa, Azure Service Bus or whatever and maybe a MongoDB and a Elastic Search (paying for enterprise licenses). 
  • Complex synchronisation: Yes, eventual consistency and also synchronising the data back to the read model can be challenging in case of failures (spoiler, Event Sourcing comes into picture to make this bullet point easier)
So, how do you feel about CQRS? If I were you, I will really consider the following points
  • For easy cases or systems I will avoid CQRS, it is an overkill.
  • Do I really need all this scalability, performance, fine grain and complexity? Always make this question. If you have a system with a reasonable amount of transactions, concurrent users and you do not expect this will grow as fast as you think...  then do not torture yourself, your customer or whoever. Why to pay for a formula 1 when you need a bycicle.
  • am I skilled enough or my team is skilled enough to implement a robust CQRS pattern? We are humans after all (like the song)

ES

In the majority of CQRS implementations you will find his brother Event Souring (ES) implemented with it. Why? Because Event Sourcing solves some complexities of CQRS and solves some of the typical use cases like data synchronisation, audit and history.

Event Sourcing


Event Sourcing is also a design pattern where the state of a system is derived from a sequence of events or in other words like an append-log that can be replayed until the moment you want to recreate the state of a particular entity or system.
Important to know in Event Sourcing:
  • Events are immutable. They cannot be updated or deleted
  • Consistency and reliability: Improves a lot these non-functional requirements as the source of truth is the log of events.
  • Enables CQRS and scalability: They pair perfectly forcing you into an event driven architecture.
I do not have much to say more about event sourcing

CQRS + ES

This diagram represents high level how they can work together.

CQRS + ES example


Comments

Popular posts from this blog

Sega Saturn Development: Where do I start

Why do I chose Camunda BPM?

Camunda 8 Self-Managed Local Environment