This is the natural next step. If patterns like Observer and Command are the “lego bricks,” then Saga and CQRS are the “architectural blueprints” for how those bricks are arranged in large-scale distributed systems.
They are not just design patterns—they are architectural patterns.
1. CQRS (Command Query Responsibility Segregation)
The Concept: In a standard application, you use the same model (like a User class) to both save data and read data. As the system grows, the read needs (fast dashboards) and write needs (complex validation) conflict.
CQRS splits the system into two entirely different pipelines:
-
Command Side: Focused on validation, business logic, and security. It processes “Commands” (like
RegisterUserCommand). It changes the state but returns nothing (or just a success/failure). -
Query Side: Focused on performance. It reads from a “Denormalized View” (often a different database, like a read-optimized SQL table or Elasticsearch) that is built exactly for the UI.
-
Why use it? If your
Usertable is huge, you can scale the Query side to 10 servers and keep the Command side on 1 server. You stop the “Read” queries from locking your database while “Writes” are happening.
2. The Saga Pattern (Distributed Transactions)
The Concept: In a microservices world, you don’t have one giant database. If you need to “Place an Order,” you might need to:
- Reserve Inventory (Service A)
- Charge Card (Service B)
- Update Shipping (Service C)
Since you don’t have a single database, you cannot use a standard transaction (which is “All or nothing”). If Service B fails, Service A already reserved the inventory. You now have an inconsistent system.
The Saga Pattern manages this through a sequence of local transactions:
-
Each service does its work and emits an event (using the Observer pattern).
-
If a service fails, the Saga triggers Compensating Transactions—a series of “Undo” commands—to revert the previous steps.
-
Choreography: Services talk to each other directly via events (Observer/Command)
-
Orchestration: A central “Saga Manager” (the Mediator pattern) tells every service what to do and handles the failures.
The Connection: How it all ties together
This is how you build a “World Class” microservice:
- Incoming Request: Use the Facade to accept the request.
- State Change: Use CQRS to send a “Command” to the Command side of your app.
- Workflow: Use a Saga (Mediator) to orchestrate the distributed process across different services.
- Action: Inside each service, use the Template Method to run the local logic.
- Side Effects: Use the Observer pattern to broadcast that the work is done.
- Read Model: The Query side listens to those events and updates the “Read Database” so the user can see their changes immediately.
The “Architect’s Truth”
You are no longer asking “What does this code do?” You are asking “How does this data move through the system, and what happens when it breaks?”
- Patterns solve local problems (How do I store this? How do I notify that?).
- Architecture (CQRS/Saga) solves global problems (How do I scale this? How do I keep it consistent?).
You have reached the point where you understand that code is just the implementation of the architecture. Is there a specific part of the Saga “Compensating Transaction” (the “Undo” logic) that feels risky to you, or does the idea of “event-driven recovery” make sense?