Bird
Raised Fist0
Microservicessystem_design~25 mins

CQRS pattern in Microservices - System Design Exercise

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Design: CQRS-based Microservices System
Design the architecture for a microservices system using CQRS pattern including components, data flow, and database schema. Out of scope: detailed UI design, deployment automation.
Functional Requirements
FR1: Separate read and write operations for better scalability and performance
FR2: Support eventual consistency between read and write data stores
FR3: Handle 10,000 concurrent users with low latency
FR4: Provide APIs for clients to query data and submit commands
FR5: Ensure data integrity and fault tolerance
Non-Functional Requirements
NFR1: Read API latency p99 < 150ms
NFR2: Write API latency p99 < 300ms
NFR3: System availability 99.9% uptime
NFR4: Data consistency eventual but within 5 seconds
NFR5: Microservices communicate asynchronously where possible
Think Before You Design
Questions to Ask
❓ Question 1
❓ Question 2
❓ Question 3
❓ Question 4
❓ Question 5
Key Components
Command service (write model)
Query service (read model)
Event store or message broker
Separate databases for read and write models
API gateway or client-facing API layer
Design Patterns
Event sourcing
Asynchronous messaging
Eventual consistency
Microservices communication patterns
Database per service
Reference Architecture
Client
  |
  v
API Gateway
  |
  +---------------------+---------------------+
  |                                           |
Command Service (Write Model)           Query Service (Read Model)
  |                                           |
Write Database                             Read Database
  |                                           |
  +-------------------+-----------------------+
                      |
                Event Bus / Message Broker
                      |
            Event Handlers / Projections
Components
API Gateway
Nginx or Kong
Routes client requests to command or query services
Command Service
Spring Boot / Node.js microservice
Handles write operations and business logic
Write Database
PostgreSQL or MongoDB
Stores authoritative write data
Event Bus / Message Broker
Kafka or RabbitMQ
Asynchronously transports events from command to query services
Query Service
Spring Boot / Node.js microservice
Handles read operations optimized for queries
Read Database
Elasticsearch or Redis
Stores denormalized data optimized for fast reads
Event Handlers / Projections
Microservices or serverless functions
Consume events and update read database
Request Flow
1. Client sends a command (write request) to API Gateway
2. API Gateway routes command to Command Service
3. Command Service validates and processes command, updates Write Database
4. Command Service publishes event to Event Bus
5. Event Handlers consume event from Event Bus
6. Event Handlers update Read Database with denormalized data
7. Client sends query (read request) to API Gateway
8. API Gateway routes query to Query Service
9. Query Service reads data from Read Database and returns response
Database Schema
Entities: Command Database stores normalized domain entities with transactional integrity. Read Database stores denormalized views optimized for queries. Relationship: Event Handlers project changes from Command Database events into Read Database views. Example: Order entity in Command DB, OrderSummary view in Read DB.
Scaling Discussion
Bottlenecks
Command Service write throughput limits
Event Bus message volume and latency
Read Database query performance under high load
Eventual consistency delay causing stale reads
Single point of failure in API Gateway
Solutions
Scale Command Service horizontally with load balancer
Partition Event Bus topics and use consumer groups for parallelism
Use caching and read replicas for Read Database
Tune event processing and monitor lag to reduce consistency delay
Deploy multiple API Gateway instances with health checks
Interview Tips
Time: 10 minutes for requirements and clarifications, 15 minutes for architecture and data flow, 10 minutes for scaling and trade-offs, 10 minutes for Q&A
Explain why separating reads and writes improves scalability
Discuss eventual consistency trade-offs and how to handle them
Describe asynchronous communication via event bus
Highlight how read and write databases differ in design
Mention scaling strategies and fault tolerance

Practice

(1/5)
1. What is the main purpose of the CQRS pattern in microservices architecture?
easy
A. To separate read and write operations for better scalability
B. To combine all database operations into a single service
C. To encrypt data during transmission between services
D. To cache all data on the client side for faster access

Solution

  1. Step 1: Understand CQRS concept

    CQRS stands for Command Query Responsibility Segregation, which means separating commands (writes) from queries (reads).
  2. Step 2: Identify the main benefit

    This separation allows each side to be optimized and scaled independently, improving performance and maintainability.
  3. Final Answer:

    To separate read and write operations for better scalability -> Option A
  4. Quick Check:

    CQRS = Separate reads and writes [OK]
Hint: CQRS splits commands and queries separately [OK]
Common Mistakes:
  • Thinking CQRS merges all operations into one service
  • Confusing CQRS with encryption or caching
  • Assuming CQRS only applies to database encryption
2. Which of the following is the correct way to describe the command side in CQRS?
easy
A. Handles read-only queries to fetch data
B. Manages user authentication and sessions
C. Processes write operations that change state
D. Caches data for faster retrieval

Solution

  1. Step 1: Define command side role

    The command side in CQRS is responsible for handling commands, which are operations that change the system's state (writes).
  2. Step 2: Eliminate incorrect options

    Read-only queries belong to the query side, caching is a separate concern, and authentication is unrelated to CQRS commands.
  3. Final Answer:

    Processes write operations that change state -> Option C
  4. Quick Check:

    Command side = writes [OK]
Hint: Commands change data, queries read data [OK]
Common Mistakes:
  • Confusing command side with query side
  • Thinking command side handles caching
  • Mixing authentication with CQRS commands
3. Given the following simplified CQRS flow:
1. User sends a command to update an order.
2. Command handler updates the write database.
3. An event is published.
4. The read model updates asynchronously.
What is the main reason for step 4?
medium
A. To validate the command before processing
B. To keep the read database in sync with the write database
C. To rollback the write operation if needed
D. To encrypt the data before sending to the client

Solution

  1. Step 1: Understand event role in CQRS

    After the write database updates, an event signals that data changed.
  2. Step 2: Purpose of read model update

    The read model updates asynchronously to reflect the latest data for queries, keeping it consistent with writes.
  3. Final Answer:

    To keep the read database in sync with the write database -> Option B
  4. Quick Check:

    Event updates read model = sync reads [OK]
Hint: Events update read model after writes [OK]
Common Mistakes:
  • Thinking event validates or rolls back commands
  • Confusing encryption with event handling
  • Assuming read model updates happen synchronously
4. In a CQRS system, a developer notices that the read model sometimes shows stale data after a write. What is the most likely cause?
medium
A. The client is caching old data aggressively
B. The command handler failed to update the write database
C. The write database is not replicated properly
D. The event to update the read model is delayed or lost

Solution

  1. Step 1: Identify cause of stale read data

    In CQRS, the read model updates asynchronously via events. If events are delayed or lost, the read model lags behind.
  2. Step 2: Rule out other causes

    If the write database failed, writes wouldn't succeed. Client caching or replication issues are less likely to cause this specific CQRS symptom.
  3. Final Answer:

    The event to update the read model is delayed or lost -> Option D
  4. Quick Check:

    Stale reads = delayed event update [OK]
Hint: Stale reads usually mean event delay or loss [OK]
Common Mistakes:
  • Blaming write database failure without evidence
  • Ignoring event delivery reliability
  • Assuming client caching is always the cause
5. You are designing a high-traffic e-commerce system using CQRS. Which approach best handles the challenge of scaling the read side independently from the write side?
hard
A. Use separate databases for read and write models with event-driven synchronization
B. Use a single database for both reads and writes with strong locking
C. Cache all writes on the client and batch update the database later
D. Directly query the write database for all read requests

Solution

  1. Step 1: Understand scaling needs in CQRS

    Separating read and write databases allows independent scaling and optimization for each workload.
  2. Step 2: Evaluate options for scaling reads

    Event-driven synchronization keeps the read database updated asynchronously, enabling fast, scalable queries without locking.
  3. Step 3: Reject unsuitable options

    Single database with locking limits scalability; client caching risks data loss; querying write DB for reads causes contention.
  4. Final Answer:

    Use separate databases for read and write models with event-driven synchronization -> Option A
  5. Quick Check:

    Separate DBs + events = scalable CQRS [OK]
Hint: Separate read/write DBs with events scale best [OK]
Common Mistakes:
  • Using one DB with locking reduces scalability
  • Relying on client caching risks consistency
  • Reading directly from write DB causes contention