avatarRakia Ben Sassi

Summary

The provided web content offers an introduction to Command Query Responsibility Segregation (CQRS), an architectural pattern that separates read and write operations in a system, and discusses its benefits, implementation, and how it fits within the broader context of software architecture paradigms such as event-driven and serverless architectures.

Abstract

The article "Command Query Responsibility Segregation (CQRS) for Dummies" provides a comprehensive overview of the CQRS architectural pattern, which is gaining popularity in the realm of Domain-Driven Design (DDD) and event sourcing. CQRS distinguishes itself by segregating the responsibilities of data read and write operations, potentially employing separate databases for each. This segregation allows for a clear separation of concerns, where microservices can focus on specific tasks, enhancing system scalability and manageability. The author, who is developing a video course titled "Decoding Software Architecture," illustrates CQRS with a case study of a YouTube-like platform, demonstrating how it handles the upload and display of new video content. The article also touches on the temporal dimension that CQRS introduces, enabling systems to track the history of changes and perform complex temporal queries. Additionally, the author draws parallels between state management in UI frameworks and event-driven architectures, emphasizing the recurring patterns in software design.

Opinions

  • The author believes that CQRS adds a new dimension to systems by incorporating time, which allows for tracking the sequence of read and write operations and building a state of the system over time.
  • CQRS is seen as a pattern that can enhance the robustness, scalability, and auditing capabilities of a system due to its ability to maintain a rich historical context of changes when paired with event sourcing.
  • The article suggests that adopting CQRS requires a cognitive shift for those accustomed to traditional architectural paradigms, indicating that it may present a learning curve.
  • The author finds it fascinating that patterns like CQRS and state management in front-end development resemble natural patterns, such as fractals, highlighting the universality of certain architectural concepts.
  • The author promotes the idea that CQRS can lead to more effective and efficient web applications, particularly when combined with event-driven architecture, by allowing for decoupled systems and enhancing scalability.

Command Query Responsibility Segregation (CQRS) for Dummies

Hands-on the CQRS architectural paradigm

The Command Query Responsibility Segregation (CQRS) architectural pattern (images by author)

This article is an excerpt from my coming video course “Decoding Software Architecture.” Subscribe to my email newsletter and get a free access to it.

Event-driven architecture (EDA), serverless architecture, and Command Query Responsibility Segregation (CQRS) architectural patterns offer unique solutions to the challenges of system design. They provide distinct benefits and considerations.

Event-driven architecture

In an event-driven architecture, services communicate with each other by producing and consuming events. Events represent significant changes or occurrences within the system.

Each service can react to events it is interested in and perform its own operations accordingly.

This approach offers loose coupling and scalability.

Serverless architecture

In a Serverless architecture, also known as Function-as-a-Service (FaaS):

  • Each function or microservice performs a specific task or business logic.
  • It’s deployed and executed in response to specific events or triggers.

In a serverless architecture, the focus is on deploying and scaling individual functions or microservices independently.

CQRS

On the other side, CQRS is an architectural pattern that separates the read and write operations in a system. It involves having separate models for reading and writing data.

This concept of separation between read/write operations and services requires from someone who worked for a long time with the other architectural paradigms, regardless of whether they are monolithic or microservices, a bit of cognitive load and a new thinking pattern.

So let’s have a look at it with more details.

This pattern has gained attention in recent years. Its concept was first introduced by Greg Young, and it has become popular in the context of Domain-Driven Design (DDD) and event sourcing.

CQRS in a Nutshell

In a CQRS system, each microservice focuses on its specific responsibility, providing a clear separation of concerns. It’s also possible to have separate databases:

  • a “write database” used only for making changes. This is known as the command side.
  • and a “read database” used only for reading the data and creating materialized views. This is known as the query side.

Case Study

Let’s imagine now that a platform like YouTube is built with the CQRS paradigm.

If the YouTube platform was built using the CQRS paradigm (screenshot by author)

In this case:

  1. when a content creator uploads a new video to the platform,
  2. it will be processed by the command service and saved in the write DB.
  3. After that a synchronization between the write and read DBs will be triggered,
  4. in order to show the viewers the newly uploaded video when they open the YouTube page or the appropriate YouTube channel.

Example of the Write Model

In this simplified example, the BlogPostService represents the write model:

Example of CQRS write model
  • It’s responsible for creating, updating, and deleting blog posts.
  • It uses the BlogPostRepository to persist the blog posts in the database.

Example of the Read Model

Here we see the BlogPostQueryService, which represents the read model responsible for querying and retrieving blog posts.

Example of CQRS read model
  • It also uses the BlogPostRepository to fetch the relevant blog posts from the database
  • and converts them into DTOs (Data Transfer Objects) for presentation.

In a real-world scenario, you would likely have more complex business logic, error handling, and additional layers (such as controllers and DTO mappings) in your application.

One advantage of the CQRS paradigm is that it adds a new dimension to your system, which is time.

When we follow and analyze the sequence of read operations and write operations over time, we can build a state of a system, which is more challenging to have with other architectural paradigms.

State Management

The funny thing here is that State management patterns are relevant at different levels of an application or a system.

UI Frameworks like Angular or React offer different mechanisms for managing client-side states.

If we zoom in, we can see that the UI State Management and Frontend Reactivity Model is similar to the Even-Driven Architecture Pattern. The difference is that in modern frontend development:

  • instead of microservices, we have microfrontends, and UI components,
  • and instead of Kafka, or AWS SQS (Simple Queue Service), we use state management with Redux for React applications, or libraries like NgRx, NgXs, or BehaviorSubject based Services, or Signals for Angular applications.

I find this fact very fascinating because it reminds me of the repeating patterns in nature like fractals.

The Time Dimension

But let’s come back to the time dimension that I mentioned with the CQRS architectural pattern.

For a better understanding of this dimension, let’s take the invoice entity as a case study. An invoice could have the status “draft”, “created”, “sent”, “paid”, or “closed.”

Classical architectural patterns typically use a “status” attribute to manage entities’ status.

How classical architectural patterns manage an entity’s status (screenshot by author)

In contrast, Event-driven architecture (EDA) leverages asynchronous, event-based communication to notify interested components (or services) about status changes. This way promotes decoupled systems and enhances scalability.

CQRS further refines this by separating the modification (command) and reading (query) of an entity’s “status”.

How Event-Driven and CQRS architectures manage an entity’s status (screenshot by author)

When paired with event sourcing, CQRS allows systems to maintain a richer historical context of changes.

Every update to an entity’s “status” can be captured as a distinct event with its timestamp.

This not only adds a clear time dimension to data changes but also enables complex temporal queries, such as:

  • Tracking the history of status changes over time, or
  • Reconstructing the past states of an entity.

Thus, CQRS inherently introduces a time dimension to system design. It emphasizes the temporal aspects of data consistency, the processing of commands and queries, and the historical tracking of changes.

This temporal consideration is crucial for designing systems that require:

  • robustness,
  • scalability,
  • and detailed auditing or
  • historical analysis capabilities.

Want more?

I write about engineering, technology, and leadership for a community of smart, curious people 🧠💡. Join my free email newsletter for exclusive access.

Join 30K+ students and enroll in my Udemy video course: Web Performance 101: Your Guide to Boost Your Web Apps, where I unravel the secrets of efficient and effective web applications 🚀.

Software Architecture
Software Engineering
Web Development
Technology
Software Development
Recommended from ReadMedium