ARCHIVED from builddistributedsystem.com on 2026-04-28 — URL: https://builddistributedsystem.com/tracks/reactor/tasks/task-27-2-1-cqrs-fundamentals
TASK

Implementation

CQRS (Command Query Responsibility Segregation) separates every operation into either a command (write, changes state) or a query (read, never changes state). Commands and queries are handled by separate buses with separate models, enabling each side to be optimised independently.

Implement a node that routes messages to the correct bus:

// Command: validate payload, apply change, return emitted events
{ "type": "CreateUser", "msg_id": 1,
  "payload": {"name": "John", "email": "john@example.com"} }
-> { "type": "command_result", "in_reply_to": 1,
    "success": true,
    "events": [{"type": "UserCreated", "payload": {"id": "<uuid>", "name": "John"}}] }

// Command validation failure
{ "type": "CreateUser", "msg_id": 2,
  "payload": {"name": "John"} }    // missing email
-> { "type": "command_result", "in_reply_to": 2,
    "success": false,
    "errors": ["Email is required"] }

// Query: read from read model, no state change
{ "type": "GetUser", "msg_id": 3,
  "params": {"user_id": "user-123"} }
-> { "type": "query_result", "in_reply_to": 3,
    "data": {"id": "user-123", "name": "John Doe"} }

The key rule: if the operation changes state, it is a command; if it only reads, it is a query. A single operation must never do both.

Sample Test Cases

Handle commandTimeout: 5000ms
Input
{
  "src": "client",
  "dest": "commandbus",
  "body": {
    "type": "CreateUser",
    "msg_id": 1,
    "payload": {
      "name": "John",
      "email": "john@example.com"
    }
  }
}
Expected Output
{"type": "command_result", "in_reply_to": 1, "success": true, "events": [{"type": "UserCreated", "payload": {"id": ".*", "name": "John"}}]}
Execute queryTimeout: 5000ms
Input
{
  "src": "client",
  "dest": "querybus",
  "body": {
    "type": "GetUser",
    "msg_id": 1,
    "params": {
      "user_id": "user-123"
    }
  }
}
Expected Output
{"type": "query_result", "in_reply_to": 1, "data": {"id": "user-123", "name": "John Doe"}}

Hints

Hint 1
Commands change state and emit events; queries only read and never mutate
Hint 2
A command handler validates the payload, applies the change, and returns the emitted events
Hint 3
A query handler reads from a pre-built read model and returns data
Hint 4
Validation failure should return success=false with an errors array
Hint 5
Route by the message type field: CreateUser goes to command bus, GetUser to query bus
OVERVIEW

Theoretical Hub

Concept overview coming soon

Key Concepts

CQRScommand busquery buscommand validationread modelwrite model separation
main.py
python
Implement CQRS Fundamentals - The Reactor | Build Distributed Systems