CQRS
Published: 2024-04-04 18:08:30

## CQRS Like You Were a 5-Year-Old

Imagine you have a **_toy box_**. When you want to play with your **_toys_**, you ask your mom to open the **_toy box_** and give you the toys you want. That's like asking a **question**, or in computer terms, a **_query_**. You're not changing anything, **_just looking at what toys you have_**.

Now, imagine after playing, you decide to put some of your `toys` back in a different way. Maybe you're putting them in order of `size` or `grouping` them by type. This time, you're not just looking; you're **_changing how things are arranged_**. In computer terms, that's like a **_command_** because you're telling the toy box (or a computer system) to **_change something_**.

**_CQRS_** stands for **_Command Query Responsibility Segregation_**.

It's a fancy way of saying that when we use computers or apps, there are two main things we can do: **_look at stuff_** (`queries`) and **_change stuff_** (`commands`). CQRS is like having two separate `toy boxes`: one for looking at toys and another for deciding how to organize them. This way, it's easier and faster to either find your `toys` or **_organize_** them, because you're not mixing up looking and changing toys in the same **_toy box_**.

### **_Now Comes the Fun Part_**

You have 2 different toy boxes: 1 to find and 1 to arrange. But if I change the arrangement of the toys in 1 box, won't the same need to be made in the other box as well, in order to maintain consistency? In the current case, the changes of arrangement are not going to reflect in the other toy box, right?

### **_Absolutely Right!!!_**

If you change how your toys are arranged in one `toy box`, you'd want the other toy box to show those changes too, so everything matches up. In our CQRS world, this means when you do something in the **_change stuff_** box, someone (usually a smart part of the computer or app) has to make sure the **_look at stuff_** box knows about those changes.

### **_Let's Continue With Our Toy Analogy_**

Imagine you have a magic notebook that keeps track of what you do in the **_change stuff_** box. Every time you move a `toy`, you write it down in the **_notebook_**. Then, there's a friendly **_elf_** who takes a look at your notebook while you're asleep, and he makes sure everything you did in the **_change stuff_** box is also done in the **_look at stuff_** box. When you wake up and decide to play again, both your boxes are up to date, and everything matches.

In computer systems, this **_magic notebook_** can be something like a list of all the changes you've made (we call these **_events_**), and the **_friendly elf_** can be a piece of software that makes sure both sides (the command side and the query side) are kept in sync. This way, whether you're looking at your data or changing it, you always see the latest version.

## **_Let's Explain How CQRS Might Work Using Node.js, MongoDB, and Any Additional Pieces Necessary to Make It Clear_**

Imagine you're building a simple app where you can add `toys` to a collection and view your collection. In a CQRS approach, you would have two main parts: `one for adding` or changing toy information (`the command side`) and `another for viewing` your toy collection (`the query side`).

### 1. MongoDB Setup

You'll use MongoDB to store your toys. But, following the CQRS principle, you might have two collections:

- **_Toys_Commands:_** This is where you add or update toy information. Think of it as the "change stuff" box.
- **_Toys_Queries:_** This collection is optimized for reading and displaying toy data. It's your "look at stuff" box.

### 2. Node.js Application

Your Node.js app will have different routes or endpoints for commands (adding/updating toys) and queries (getting toy information).

#### **_Command Side_**

When you want to add a new toy or update an existing one, you'll use a command endpoint like POST `/toys` or **_PUT_** `/toys/:toyId`. This part of the app will interact with the Toys_Commands collection. When a toy is added or updated, the app will also send a message (let's think of it as our "magic notebook" entry) to a messaging system (like RabbitMQ or Kafka), indicating what change was made.

#### **_Query Side_**

The query part of the app has endpoints like `GET /toys` to view the toy collection. It reads from the **_Toys_Queries_** collection, which is optimized for fast, read-only access.

#### **_Keeping Things in Sync_**

Now, we need our `friendly elf` to keep the command and query sides in sync. This can be a separate service or part of your app that listens for messages about changes made on the command side (our `magic notebook`). When it receives a message about a change, it updates the **_Toys_Queries_** collection accordingly. This way, the next time you go to view your `toys`, the collection is up-to-date with all the latest changes.

### **_Additional Pieces_**

#### **_Messaging System (RabbitMQ/Kafka):_**

This acts as the intermediary that passes messages from the command side to the service responsible for updating the query side. It ensures that all changes are queued and processed reliably.

#### **_Separate Services/Workers for Syncing:_** 

These are specialized parts of your app (or separate apps) that listen to the messaging system and update the query side based on the command side's changes.

### **Example Flow**

#### **_Add a Toy (Command):_** 

You send a request to `POST /toys` to add a new toy. The toy is added to **_Toys_Commands_**, and a message is sent to RabbitMQ noting the addition.

#### **_Syncing:_** 

A separate service listens to RabbitMQ, receives the message about the new toy, and adds this toy to **_Toys_Queries_**.

#### **_View Toys (Query):_** 

When you request `GET /toys`, the app reads from **_Toys_Queries_**, showing you the latest collection, including the toy you just added.

This setup, with Node.js, MongoDB, and a messaging system, helps keep your app organized according to CQRS principles, separating the concerns of modifying data and reading it, while also ensuring consistency between those views.