Bird
Raised Fist0
HLDsystem_design~10 mins

CQRS (Command Query Responsibility Segregation) in HLD - Scalability & System Analysis

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
Scalability Analysis - CQRS (Command Query Responsibility Segregation)
Growth Table: CQRS at Different Scales
UsersCommands (Writes)Queries (Reads)Data StorageLatencyComplexity
100 usersLow volume, single write DBLow volume, single read DBSingle DB instanceLow latency, simple syncSimple CQRS setup
10,000 usersModerate writes, DB scaling neededHigh reads, read DB replicasPrimary + read replicasEventual consistency visibleSeparate read/write DBs
1 million usersHigh writes, sharded command DBVery high reads, distributed read DBSharding + replicationIncreased eventual consistency delayEvent sourcing may be added
100 million usersMassive writes, multi-region shardsExtreme reads, global caches/CDNsGeo-distributed DB clustersConsistency trade-offs, async syncComplex event sourcing + CQRS
First Bottleneck

At small scale, the database handling writes (command side) is the first bottleneck because all changes must be processed and stored reliably. As users grow, the write DB CPU and disk I/O limits are reached first.

Read side scales easier with replicas, so write DB capacity is the main limit initially.

Scaling Solutions
  • Vertical scaling: Increase CPU, RAM, and disk speed on command DB server to handle more writes.
  • Horizontal scaling: Shard the command database by user or entity to distribute writes across servers.
  • Read replicas: Add multiple read-only replicas to serve queries and reduce load on primary DB.
  • Caching: Use in-memory caches (e.g., Redis) on query side to speed up frequent reads.
  • Event sourcing: Store changes as events to enable replay and rebuild read models asynchronously.
  • Asynchronous sync: Decouple command and query sides with message queues to improve write throughput.
  • Geo-distribution: Deploy DB clusters in multiple regions to reduce latency for global users.
Back-of-Envelope Cost Analysis

Assuming 1 million users with 10% active concurrently:

  • Concurrent users: 100,000
  • Writes per second (commands): ~5,000 QPS (assuming 5% write rate)
  • Reads per second (queries): ~95,000 QPS (assuming 95% read rate)
  • Storage: Command DB stores events/transactions, estimated 1TB/month
  • Read DB stores denormalized views, estimated 2TB for fast queries
  • Network bandwidth: Reads dominate, ~1 Gbps needed for query responses
Interview Tip

Start by explaining the separation of commands and queries and why it helps scalability.

Discuss bottlenecks on the write side first, then read side.

Outline scaling steps: vertical scaling, read replicas, sharding, caching, and asynchronous event processing.

Use real numbers to show understanding of limits and solutions.

Self Check Question

Your database handles 1000 QPS writes. Traffic grows 10x to 10,000 QPS writes. What do you do first?

Answer: Implement sharding of the command database to distribute write load across multiple servers, because vertical scaling alone likely won't handle 10x increase efficiently.

Key Result
CQRS scales well by separating write and read workloads; the write database is the first bottleneck and requires sharding and asynchronous processing to handle large user bases.

Practice

(1/5)
1. What is the main purpose of using CQRS in system design?
easy
A. To encrypt data for security purposes
B. To combine all database operations into a single service
C. To separate read and write operations for better scalability
D. To reduce the number of servers needed

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 part to be optimized and scaled independently, improving performance and maintainability.
  3. Final Answer:

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

    CQRS = Separate reads and writes [OK]
Hint: CQRS splits commands and queries for scaling [OK]
Common Mistakes:
  • Thinking CQRS combines operations into one service
  • Confusing CQRS with security encryption
  • Assuming CQRS reduces server count directly
2. Which of the following is the correct way to describe the role of the 'Command' in CQRS?
easy
A. It processes write operations that change system state
B. It handles read-only queries to fetch data
C. It stores cached data for faster access
D. It manages user authentication and authorization

Solution

  1. Step 1: Define Command role in CQRS

    Commands are responsible for write operations that modify the system's state.
  2. Step 2: Differentiate from Query

    Queries only read data without changing it, so they are not commands.
  3. Final Answer:

    It processes write operations that change system state -> Option A
  4. Quick Check:

    Command = Write operations [OK]
Hint: Commands change data; queries only read [OK]
Common Mistakes:
  • Confusing commands with queries
  • Thinking commands handle caching
  • Assuming commands manage security
3. Consider a system using CQRS where the write side updates a user profile and the read side serves user data. If the write side updates the user's email, what is the expected behavior on the read side immediately after the update?
medium
A. The read side instantly shows the updated email without delay
B. The read side deletes the user data until refreshed
C. The read side rejects the query until the write completes
D. The read side may show the old email briefly due to asynchronous update

Solution

  1. Step 1: Understand asynchronous update in CQRS

    In CQRS, the read side is often updated asynchronously via events after the write completes.
  2. Step 2: Identify read side behavior after write

    Because of this delay, the read side may temporarily show stale data until it receives the update event.
  3. Final Answer:

    The read side may show the old email briefly due to asynchronous update -> Option D
  4. Quick Check:

    Read side updates asynchronously = possible stale data [OK]
Hint: Reads update asynchronously, so data may lag briefly [OK]
Common Mistakes:
  • Assuming immediate read consistency
  • Thinking reads block until writes finish
  • Believing read data is deleted during update
4. A developer implemented CQRS but notices that the read model is not updating after commands execute. What is the most likely cause?
medium
A. The read model database is corrupted and cannot be read
B. The command handler is not sending events to update the read model
C. The query side is trying to write data instead of reading
D. The system is using synchronous updates causing deadlocks

Solution

  1. Step 1: Identify how read model updates in CQRS

    The read model updates via events sent by the command handler after state changes.
  2. Step 2: Diagnose missing updates

    If the read model is not updating, likely the events are not being sent or processed properly.
  3. Final Answer:

    The command handler is not sending events to update the read model -> Option B
  4. Quick Check:

    Missing events cause read model stale data [OK]
Hint: Check if events are sent after commands [OK]
Common Mistakes:
  • Blaming database corruption without evidence
  • Confusing query side roles
  • Assuming synchronous updates cause deadlocks here
5. You are designing a high-traffic e-commerce system using CQRS. Which approach best ensures that the read side remains highly available and scalable while keeping data reasonably fresh?
hard
A. Use event sourcing to asynchronously update read models and deploy multiple read replicas
B. Use a single database for both reads and writes to avoid data duplication
C. Synchronously update the read model within the command transaction to ensure consistency
D. Disable caching on the read side to always fetch fresh data from the write database

Solution

  1. Step 1: Understand scalability needs in CQRS

    Separating reads and writes allows scaling read replicas independently to handle high traffic.
  2. Step 2: Use event sourcing for asynchronous updates

    Event sourcing helps keep read models updated asynchronously, balancing freshness and availability.
  3. Step 3: Evaluate other options

    Single database limits scalability; synchronous updates reduce availability; disabling caching hurts performance.
  4. Final Answer:

    Use event sourcing to asynchronously update read models and deploy multiple read replicas -> Option A
  5. Quick Check:

    Event sourcing + read replicas = scalable, fresh reads [OK]
Hint: Event sourcing + replicas = scalable reads with freshness [OK]
Common Mistakes:
  • Using single DB limits scalability
  • Synchronous updates reduce availability
  • Disabling cache hurts performance