Cqrs
Chapter 14: CQRS Pattern
Section titled “Chapter 14: CQRS Pattern”Command Query Responsibility Segregation
Section titled “Command Query Responsibility Segregation”14.1 What is CQRS?
Section titled “14.1 What is CQRS?”CQRS stands for Command Query Responsibility Segregation - a pattern that separates read and write operations into different models.
Traditional vs CQRS ===================
TRADITIONAL (CRUD): +----------------------------------+ | Single Model | | +-------------------------+ | | | UserService | | | | - createUser() | | | | - updateUser() | | | | - getUser() | | | | - listUsers() | | | +-------------------------+ | | | | +----------------|-----------------+ v +---------+ |Database | +---------+
CQRS: +-------------------+ +-------------------+ | Command Model | | Query Model | | | | | | - createUser() | | - getUser() | | - updateUser() | | - listUsers() | | | | - searchUsers() | +-------------------+ +-------------------+ | | v v +-------------------+ +-------------------+ | Write Database | | Read Database | | (Normalized) | | (Denormalized) | +-------------------+ +-------------------+14.2 Command vs Query
Section titled “14.2 Command vs Query”In Code Terms
Section titled “In Code Terms” Command (Write) ===============
public class CreateOrderCommand { private String userId; private List<OrderItem> items; private ShippingAddress address; }
public class CommandHandler { public void handle(CreateOrderCommand cmd) { // Validate // Business logic // Save to write DB // Publish event } }
Query (Read) ============
public class OrderQuery { public List<OrderSummary> getRecentOrders(String userId); public OrderDetails getOrderDetails(String orderId); public List<OrderSummary> searchOrders(String query); }14.3 CQRS Implementation
Section titled “14.3 CQRS Implementation”With Event Sourcing
Section titled “With Event Sourcing” Complete CQRS Flow ==================
+---------+ +----------+ +----------+ +----------+ | Client | --> | Command | --> | Command | --> | Event | | Request| | Handler | | Processor| | Store | +---------+ +----------+ +----------+ +----------+ | +---------+ +----------+ +----------+ +----------+ | | Client | <-- | Query | <-- | Read | <-- |Projector| | | Response| | Handler | | Store | | |<-+ +---------+ +----------+ +----------+ +----------+
1. Command arrives -> Validated -> Processed -> Event stored 2. Event published -> Projector updates read store 3. Query reads from optimized read storeWith Separate Databases
Section titled “With Separate Databases” Dual Database Approach =====================
Write Database (OLTP): +--------------------+ | PostgreSQL | | - Normalized | | - ACID | | - Current state | +--------------------+
Read Database (OLAP/Denormalized): +--------------------+ +--------------------+ | MongoDB | | Elasticsearch | | - User profiles | | - Search | +--------------------+ +--------------------+ +--------------------+ +--------------------+ | Redis | | ClickHouse | | - Sessions | | - Analytics | +--------------------+ +--------------------+14.4 Benefits of CQRS
Section titled “14.4 Benefits of CQRS”Advantages
Section titled “Advantages”| Benefit | Description |
|---|---|
| Independent Scaling | Scale reads/writes separately |
| Optimized Read/Write | Each model optimized for purpose |
| Different Models | Read model can be denormalized |
| Performance | Queries don’t impact writes |
| Flexibility | Multiple read views |
| Complex Domains | Clearer commands vs queries |
14.5 Use Cases
Section titled “14.5 Use Cases”When CQRS Shines
Section titled “When CQRS Shines”| Use Case | How CQRS Helps |
|---|---|
| E-commerce | Multiple views: order list, details, analytics |
| Social Media | Feeds, timelines, notifications |
| Reporting | Heavy queries don’t slow writes |
| Real-time | Different views for different clients |
| Microservices | Each service can have own models |
Example: E-commerce
Section titled “Example: E-commerce” E-commerce Read Models ======================
Write: Order Created
Read Models: +--------------------+ +--------------------+ | Customer View | | Admin View | | - My orders | | - All orders | | - Order details | | - Analytics | +--------------------+ +--------------------+
+--------------------+ +--------------------+ | Shipping View | | Financial View | | - Tracking info | | - Revenue | | - Delivery status | | - Tax reports | +--------------------+ +--------------------+14.6 Challenges
Section titled “14.6 Challenges”Complexities
Section titled “Complexities”| Challenge | Description |
|---|---|
| Complexity | Two models to maintain |
| Consistency | Eventual consistency between models |
| Learning Curve | Team must understand pattern |
| Testing | More components to test |
| Debugging | Harder to trace issues |
Handling Consistency
Section titled “Handling Consistency” Eventual Consistency ===================
Timeline:
Time 0: User creates order | v Time 1: Write DB updated (order created) | v Time 2: Event published to message queue | v Time 3: Projector updates read DB (ms to seconds) | v Time 4: All read models consistent
User Experience: - Order created immediately (write confirmed) - May see "processing" briefly in read view - Usually within milliseconds14.7 Read Models
Section titled “14.7 Read Models”Different Views
Section titled “Different Views” Multiple Read Models ====================
One Command -> Multiple Read Models
Command: Create Order
Read Models: 1. Customer Orders List - Simplified (id, date, total, status)
2. Order Details - Full order with items
3. Shipping Tracker - Shipping status, tracking number
4. Analytics - Aggregated revenue, counts
5. Search Index - Full text searchable14.8 Implementation Patterns
Section titled “14.8 Implementation Patterns”Synchronous vs Asynchronous
Section titled “Synchronous vs Asynchronous” Synchronous (Simple) ====================
Client -> Handler -> Write DB -> Return | v Read DB (synchronous update)
Pros: Simple, eventual consistency window smaller Cons: Write latency includes read update
Asynchronous (High Performance) ==============================
Client -> Handler -> Write DB -> Return | v Event Queue | v Projector (async) | v Read DB
Pros: Fast writes, scalable Cons: Larger consistency window14.9 Best Practices
Section titled “14.9 Best Practices”Implementation Tips
Section titled “Implementation Tips”| Practice | Description |
|---|---|
| Start simple | Don’t CQRS until needed |
| Separate models | Commands and queries clearly |
| Event sourcing | Works well with CQRS |
| Multiple views | Optimize each read use case |
| Handle lag | Show “updating” state if needed |
| Monitor | Track consistency lag |
Summary
Section titled “Summary”Key CQRS concepts:
- Separate reads/writes - Different models for different purposes
- Command = write - Intent and validation
- Query = read - Optimized for specific views
- Eventual consistency - Read models may briefly lag
- Multiple views - Different read models for different needs
- Complex - Use when benefits outweigh complexity
- Works with event sourcing - Natural fit