Event Sourcing CQRS is a popular pattern to build microservices architecture. In essence, these are two separate patterns. In other words, we can implement these patterns individually. However, in many use-cases, it becomes important to use Event Sourcing and CQRS in conjunction.

In this series of posts, we will implement an example use-case using Event Sourcing CQRS principle. Basically, at the end of this series, we will have a Event Sourcing CQRS example.

Below is my high-level plan for this series of posts.

In Part 1 (this part), we will discuss the concepts of Event Sourcing and CQRS. Also, we will talk about the example application we will be building. We will also describe the tech stack we will be using for the same.

In Part 2, we start with implementing the Event Sourcing part of our example application.

In Part 3, we implement the CQRS part of our sample application and also test the entire process.

So let’s start with the first point.

What is Event Sourcing?

Event Sourcing is a design pattern to build microservices. The concept behind Event Sourcing is that any change to the state of an entity should be captured by the system. In other words, any modification to an entity’s state should be persisted.

Let’s take a simple example to understand the concept.

Assume that we have a bank account in Bank XYZ. To manage such user accounts, the bank’s systems can have an Accounting application. Basically, this job of this application is to keep track of all the transactions happening on a user account. Therefore, we can safely assume that Account is our entity in this case.

Taking a step further, let’s assume that the below activities happened for the account we have in Bank XYZ.

  • Account creation with initial balance of 1000 USD.
  • Set account status to ACTIVE.
  • A long absconding friend returns the money for a shared meal. Deposit of 100 USD into the account.
  • Buy ice-cream for girlfriend. In other words, 150 USD gone from account!
  • The girlfriend did not like the ice-cream. And so you had to buy another one. Basically, 150 USD gone again!!
  • We forgot to pay our house rent on time. Penalty of 900 USD!!!!
  • Account status on HOLD because of negative balance.
  • Deposit of 500 USD back into the account.
  • Account status ACTIVE again.

All of the above can happen in a single day (a pretty tough day, though). But it gives us an indication of how many things can happen to an entity in a short amount of time.

How is the data stored?

In a typical database entry, the information about the account after all the transactions will look something like below:

Entity IdAmountCurrencyStatus
XYZ567823400.00USDACTIVE

However, in the Event Sourcing approach, it will appear as below:

Entity IdEventEvent Payload
XYZ567823AccountActivatedEvent{…}
XYZ567823AccountBalanceUpdatedEvent{…}
XYZ567823AccountHeldEvent{…}
XYZ567823AccountBalanceUpdatedEvent{…}
XYZ567823AccountBalanceUpdatedEvent {…}
XYZ567823AccountBalanceUpdatedEvent {…}
XYZ567823AccountBalanceUpdatedEvent{…}
XYZ567823 AccountActivatedEvent{…}
XYZ567823 AccountBalanceUpdatedEvent{…}
XYZ567823 AccountCreatedEvent{…}

This is the fundamental difference when we look at Event Sourcing.

What is CQRS?

CQRS stands for Command Query Responsibility Segregation.

What CQRS says is that the “model to update some information can be different to the model that is needed to read that information“.

Basically, this means commands (update or create operations) have different models than queries (read operations)

Let’s imagine a situation to understand it better.

In our previous example, we have an Accounting application to manage accounts. Basically, it stores everything that happens on an account in the form of events.

We also have another application that manages the customer data. We can call this application as Customer application. This application only deals with basics customer data.

Now, let’s also consider a third application. The job of this third application is to generate account statements. Therefore, we can call it the Statement application. However, to perform its job, the Statement application needs to aggregate the data from both the Customer application and the Accounting application.

event sourcing cqrs case

Why Event Sourcing CQRS?

The above example shows the advantages we can derive by combining Event Sourcing and CQRS principles together to build our applications.

If you see the illustration in the previous section, we have three applications to build over here. In other words, we can think of these applications as three separate microservices.

  • The Customer microservice deals with managing the customer data. Basically, it allows us to create a customer, update customer information and so on.
  • The Account microservice manages the account information. It utilizes Event Sourcing to store the data.
  • Lastly, the Statement microservice allows customers to obtain their account statements. However, to generate the statement, the Statement microservice will use the data managed by the Customer microservice and the Account microservice.

Together, these three applications implement the Event Sourcing and CQRS pattern.

Some advantages of this pattern are as follows:

  • Each microservice is responsible for its own data. In other words, the Customer service and the Account service are loosely coupled.
  • Individual services can scale up or down independently of each other.
  • Also, different styles of data persistence can be used for different services. Basically, the data persistence mechanism can support the use-case of a particular service.

Building the Event Sourcing CQRS Example

Now that we are clear on the concept behind Event Sourcing and CQRS, we can plan for the implementation.

Considering our example case about Customer, Accounts and Statements, we will be building the below setup.

event sourcing cqrs implementation

Let’s understand what we will be doing in each part of this overall setup.

As you can see in the illustration, we will have separate services our customer, accounts and statements. The Customer service and Account service will basically publish events through a message broker. The Statement service will subscribe to the messages. Upon receiving a message from customer or account service, the Statement service will update its query database. In other words, the statement data will be eventually consistent but highly optimized for querying purpose.

Another important point here is also the fact that each of these services can be scaled up or down independently. Usually, in such a scenario, we will notice that customer service might be least used in terms of overall load. However, account transactions will be significantly more as customer perform transactions using their account. Also, statement requests could be even more with larger volumes of data as well. Hence, the statement service might have to be scaled separately. Basically, by using Event Sourcing and CQRS, this is possible.

Understanding the Individual Services

Let’s look at the individual services in detail and also the tech stack we will be using for them.

  • Customer Service – In this service, we will manage the customer data. In other words, the commands associated with handling customer information. We will utilize Spring Boot and H2 database for our sample application. Also, customer service will publish changes to the entity. For doing so, we will use Spring Data JPA’s Domain Event functionality.
  • Account Service – In this service, we will handle the commands for the account entity. Here also, we will use Spring Boot to build our service. However, we will integrate Spring Boot with Axon server. Basically, Axon server will act as our Event Store and also provide an easy way to store and manage events. The events will also be published.
  • Statement Service – This service will handle the queries for the statements. Basically, the role of this service is to maintain query views depending on the business need. However, to do so, it will listen to messages from the message broker and update the database. In other words, this service will keep updating the data for queries in an optimized manner so that consumers don’t have to query the event store to read information. For this application, we will again be using Spring Boot. However, for our query store we will use a NoSQL database such as MongoDB. Basically, Spring Data MongoDB provides seamless integration between Spring Boot and MongoDB
  • Message Broker – Lastly, we need a message broker to exchange messages between the services. In this example, we will use RabbitMQ as our message broker. Also, we will use Spring Cloud Stream to connect our Spring Boot applications to RabbitMQ.

Conclusion

Concluding with this part of the series, we now have a plan to proceed further. We also understand the concept behind Event Sourcing and CQRS. Also, we have understood how it can be implemented using popular frameworks.

In the next part in this special series, we will start with the implementation of the Account service and the Customer service.

If you have any queries or comments about this part, please write in the comments section below.


Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

8 Comments

Ronit · May 18, 2020 at 3:43 pm

Hi Saurabh,

Would be helpful if you can guide to the link to the rabbit mq implementation referred in the above arch diagram.

Alexander · November 19, 2020 at 10:49 am

Thank you for this article serie. I’m exactly here in my project right now an trying to understand which direction we could take.
Question i have is
As far i see it Axon Server is EventStorage. Designed for it and used for it. and it can push events like Rabbit or? At least every Server can subscribe to this events…

Why do we still need RabbitMQ if we have Axon Server?

    Saurabh Dashora · November 25, 2020 at 3:11 am

    Hi Alexander, I’m glad the article helps you.

    With regards to your question, yes Axon Server can push events if needed. However, in an enterprise environment, different teams might adopt different tools and not everyone may want to register their services on the shared Axon server. In that case, we might need to use other integration mechanisms. In the end, it all depends on the overall strategy of your product or application.

Sanket · March 28, 2022 at 2:29 pm

Hi, Why are you not using Axon server here. Can it replace Rabbit MQ ? When should we use Axon server vs Message queues ?

    Saurabh Dashora · March 29, 2022 at 3:58 am

    Hi Sanket,

    Yes, we can build our application without using Axon server. RabbitMQ can take care of the messaging part. Axon Server provides some capabilities that might make our work easier. But it is definitely not a hard requirement for building microservices.

Sanket · March 28, 2022 at 2:32 pm

Hi, Why are you not using Axon server ? Can it replace message queues ? And when do we use what ?

    Saurabh Dashora · March 29, 2022 at 4:01 am

    Answered in previous question.

    To add to the last question, the choice to use a particular tool depends on your overall enterprise objectives. Axon is a third-party framework that a particular organization may or may not want to use. However, Axon does provide some really good out-of-the-box features.

Leave a Reply

Your email address will not be published. Required fields are marked *