CQRS Pattern using Spring Boot version 3 and Axon Framework/Server

Patroclos Lemoniatis
4 min readFeb 9, 2024

What is CQRS?

CQRS stands for Command and Query Responsibility Segregation, a pattern that separates read and update operations for a data store. CQRS was introduced by Greg Young in 2010.

It Seggregates the responsibilities of the commands and queries in a system. Which means we are splitting the model into read and write. On top of that, command and read handling is seperated as well.

Write model is made up from the commands, and should be as close as possible to the business processes.

A query returns the result but does not change the state. As queries do not change the state of the objects, they do not need to involve the Domain Model.

A common misconception is that Command and Queries should run on seperate databases. This is not true since only the responsibilities should be seperated.

CQRS is applicable to the behaviour of the system and not where the data is stored

Often goes hand-in-hand with Event Sourcing.

Benefits of CQRS

  • Performance

By seperating read and write models, you can optimize each model accoringly for large scale systems.

  • Scalability

Read and Write model can be scaled independently according to the system workload.

  • Flexibility

Possible to choose seperate write and read databases, as to accomodate the needs for each aspect of the system.

  • Event Sourcing

Audit log, versioning and time travel capabilities

Event Sourcing

Is a pattern for storing data as events in an append-only event store. An event represents a true event that took place in a business. Every change to the business state, is being appended to the event store.

Event sourcing is great for keeping audit logs, as it also keeps the context of the object changed. Which answers the ‘what’ changed question, in an audit log.

Some advantages of event sourcing are

  • Audit log: Keeping detailed audit logs
  • Time travel: Resetting the business model to a previous state
  • Root cause analysis: Possible to investigate the root of an issue occured, by repeating an entire workflow from beginning to the end.
  • Event Driven Architecture: Enabling the advantages of aynchronous architecture and subscribing to events for producing notifications, activating workflows based on the business events etc …

Lets start with the Event Store

For storing events we can use Axon Server and Framework which provides the whole setup for storing events.

What is Axon Framework?

Is an open source framework for building event-driven microservices and domain-driven design systems.

Based on architectural principles, such as Domain-Driven Design (DDD) and Command-Query Responsibility Segregation (CQRS), the Axon Framework provides the building blocks that CQRS requires and helps create scalable and extensible applications while maintaining application consistency in distributed systems¹

What is Axon Server?

Is a ready to use message router and an event store. It serves two purposes

  • It routes messages (commands, queries, and events) between distributed components (microservices).
  • It stores events allowing distributed (often event sourced) applications to have a single source of a state repository.

Use case scenario

A warehouse software system is handling inventory items.

A user is able to run multiple processes on the items. 2 of these processes are Create Inventory Items and Stock Adjustment (Increase / Decrease).

Important to note, this system is being accessed, by thousand of users, since it is connected to an online store, that displays the availability of the products.

Inventory items stock counter is being updated frequently. In addition, queries are being executed for stock retrieval in parallel to the updates.

On top of that, for every stock update, system needs to keep a detailed Audit Log of what changed, when and by who.

Problem,

is that system is experiencing a lot of database WRITE operations back-pressure. Plus, a huge amount of READ operations, are retrieving reduntant data from the inventory item tables. We need to to adjust the READ queries to minimize the time needed to fetch these information from the database.

Consequently, a solution, is to use CQRS with Event Sourcing

Data reads must be fine-tuned separately from performance of data writes.

We need to seperate the model into 2 parts, the WRITE and READ model. This will allow the developers to refactor and fine-tune the WRTIE commands, which in turn will be added to a message queue. By introducing a message queue we are controlling the flow of the transactions to be executed by the database.

While this will significally reduce the performance bottleneck of the database on WRITE operatios, at the same time we are exchanging performance with cosistency of data. Validity of data is affected since there is a chance, a stock update to be delayed, a few minutes or more, until is reflected on the READ database.

There is no need for the Available stock on the online store item’s page, to be 100% accurate, since it is an estimate value. On the Checkout page though, the available stock has to be retrieved from the Event-Store, in order to replay all the events and calculate the items latest state and available stock.

A high-level diagram of the Inventory Service with CQRS Event Sourcing pattern

--

--