Full Stack • Java • System Design • Cloud • AI Engineering

CQRS (Command Query Responsibility Segregation) Pattern

Learn the CQRS Pattern from a System Design perspective. Understand how CQRS separates read and write operations, improves scalability, integrates with Event Sourcing, Kafka, Spring Boot, Redis, Elasticsearch, and real-world architectures used by Amazon, Netflix, Uber, and Banking systems.


Introduction

Imagine you're designing an e-commerce platform similar to Amazon.

Daily traffic:

  • 50 Million Users
  • 800 Million Product Views
  • 20 Million Orders
  • 500 Million Product Searches

The workload is very different.

Read Operations

  • Product Search
  • Product Details
  • Reviews
  • Recommendations
  • Order History

Write Operations

  • Place Order
  • Update Inventory
  • Add Product
  • Process Payment
  • Cancel Order

Most applications receive 90-95% reads and only 5-10% writes.

If both reads and writes use the same database and same service,

eventually the system becomes difficult to scale.

The solution is CQRS.


Learning Objectives

After completing this article, you'll understand:

  • What is CQRS?
  • Why CQRS?
  • Commands vs Queries
  • Read Model
  • Write Model
  • Event Flow
  • Eventual Consistency
  • Kafka Integration
  • Spring Boot Architecture
  • Event Sourcing
  • Real-world Examples
  • Best Practices

What is CQRS?

CQRS stands for

Command Query Responsibility Segregation

It separates

  • Write Operations (Commands)
  • Read Operations (Queries)

Instead of

One Service

↓

Read

Write

CQRS creates

Write Service

↓

Database

↓

Events

↓

Read Database

↓

Read Service

Traditional Architecture

flowchart TD
    USER[Users]

    APP[Spring Boot]

    DB[(Database)]

    USER --> APP
    APP --> DB

Both reads and writes share one database.


CQRS Architecture

flowchart LR
    USER[Users]

    CMD[Command Service]

    WRITE[(Write Database)]

    KAFKA[Kafka]

    READ[(Read Database)]

    QUERY[Query Service]

    USER --> CMD
    USER --> QUERY

    CMD --> WRITE
    WRITE --> KAFKA
    KAFKA --> READ

    QUERY --> READ

Reads and writes scale independently.


Command Side

Commands change data.

Examples

  • Create Order
  • Update Product
  • Cancel Order
  • Transfer Money
  • Register User

Commands

Always Modify Data

Query Side

Queries never modify data.

Examples

  • Search Products
  • View Orders
  • Get Customer
  • Product Reviews
  • Dashboard Reports

Queries

Read Only

Command Flow

flowchart TD
    CLIENT[Client]

    API[Command API]

    SERVICE[Command Service]

    DB[(Write Database)]

    CLIENT --> API
    API --> SERVICE
    SERVICE --> DB

Query Flow

flowchart TD
    CLIENT[Client]

    API[Query API]

    READ[(Read Database)]

    CLIENT --> API
    API --> READ

Complete CQRS Flow

sequenceDiagram
    participant User
    participant Command
    participant WriteDB
    participant Kafka
    participant ReadDB
    participant Query

    User->>Command: Place Order
    Command->>WriteDB: Save Order
    WriteDB->>Kafka: OrderCreated Event
    Kafka->>ReadDB: Update Read Model

    User->>Query: Get Orders
    Query->>ReadDB: Read Orders

Why CQRS?

Without CQRS

flowchart TD
    READ[Millions of Reads]

    WRITE[Thousands of Writes]

    DB[(Single Database)]

    READ --> DB
    WRITE --> DB

Problems

  • Read bottleneck
  • Lock contention
  • Complex indexing
  • Difficult scaling

With CQRS

flowchart TD
    READ[Read Traffic]

    WRITE[Write Traffic]

    READDB[(Read Database)]

    WRITEDB[(Write Database)]

    READ --> READDB
    WRITE --> WRITEDB

Reads and writes no longer compete.


Read Model

Optimized for

  • Fast Search
  • Reporting
  • Analytics
  • Dashboards

Often uses

  • Redis
  • Elasticsearch
  • OpenSearch
  • MongoDB

Write Model

Optimized for

  • Transactions
  • ACID
  • Consistency

Typically uses

  • PostgreSQL
  • MySQL
  • Oracle
  • SQL Server

Event Publishing

Whenever data changes,

an event is published.

flowchart LR
    WRITE[(Write DB)]

    EVENT[Order Created]

    KAFKA[Kafka]

    READ[(Read Model)]

    WRITE --> EVENT
    EVENT --> KAFKA
    KAFKA --> READ

Eventual Consistency

Read Database may update slightly later.

Order Created

↓

50 ms

↓

Read Database Updated

This delay is called

Eventual Consistency.


Product Search Example

Customer

Search Laptop

Request goes directly to

Read Database

instead of transactional database.

Very fast.


Banking Example

Write Side

  • Money Transfer
  • Deposit
  • Withdraw

Read Side

  • Account Statement
  • Transaction History
  • Dashboard

Money transfers always use the write database.


Amazon Example

Command Side

  • Place Order
  • Update Inventory
  • Add Product

Query Side

  • Product Search
  • Recommendations
  • Reviews
  • Order History

Netflix Example

Commands

  • Watch Movie
  • Update Profile
  • Subscription

Queries

  • Trending
  • Recommendations
  • Search
  • Watch History

Uber Example

Commands

  • Book Ride
  • Cancel Ride
  • Payment

Queries

  • Driver Search
  • Ride History
  • ETA
  • Fare Estimate

Event Sourcing + CQRS

Very common combination.

flowchart LR
    CMD[Command]

    EVENTS[Event Store]

    PROJECTION[Projection]

    READ[(Read Database)]

    CMD --> EVENTS
    EVENTS --> PROJECTION
    PROJECTION --> READ

Instead of storing only current state,

every change is stored as an event.


Spring Boot Architecture

flowchart TD
    CLIENT[React]

    API[Spring Boot API]

    CMD[Command Service]

    QUERY[Query Service]

    WRITE[(PostgreSQL)]

    READ[(Redis/OpenSearch)]

    KAFKA[Kafka]

    CLIENT --> API

    API --> CMD
    API --> QUERY

    CMD --> WRITE
    WRITE --> KAFKA
    KAFKA --> READ

    QUERY --> READ

CQRS with Kafka

sequenceDiagram
    participant Service
    participant Kafka
    participant Projection
    participant ReadDB

    Service->>Kafka: Publish Event
    Kafka->>Projection: Consume Event
    Projection->>ReadDB: Update Read Model

CQRS Benefits

  • Independent Scaling
  • Faster Reads
  • Better Performance
  • Better Reporting
  • Different Databases
  • Reduced Lock Contention
  • Microservice Friendly

CQRS Challenges

  • More Infrastructure
  • Eventual Consistency
  • Event Handling
  • More Code
  • More Monitoring
  • Higher Operational Cost

When NOT to Use CQRS

Avoid CQRS when

  • Small CRUD Applications
  • Internal Tools
  • Admin Panels
  • Low Traffic Systems
  • Simple Monoliths

Traditional CRUD is usually simpler.


When to Use CQRS

Use CQRS for

  • Banking
  • E-commerce
  • Healthcare
  • Trading Systems
  • ERP
  • Large SaaS Platforms
  • Event-Driven Systems
  • High-Traffic Applications

CQRS vs CRUD

CRUD CQRS
Same Model Separate Models
One Database Read & Write Databases
Simple Complex
Small Systems Enterprise Systems
Easy Maintenance Better Scalability

Monitoring

Monitor

  • Kafka Lag
  • Event Processing Time
  • Read Model Delay
  • Command Latency
  • Query Latency
  • Failed Events
  • Dead Letter Queue
  • Database Throughput

Tools

  • Datadog
  • Grafana
  • Prometheus
  • Kafka UI
  • OpenSearch Dashboard
  • CloudWatch

Common Mistakes

❌ Using CQRS for simple CRUD applications

❌ Ignoring eventual consistency

❌ No retry mechanism for events

❌ No Dead Letter Queue

❌ Updating the Read Model synchronously

❌ Large command handlers


Best Practices

  • Keep Commands and Queries completely separate.
  • Publish immutable events.
  • Use Kafka or RabbitMQ for asynchronous communication.
  • Build optimized read models.
  • Monitor event lag.
  • Make event consumers idempotent.
  • Implement retry and Dead Letter Queue (DLQ).
  • Use CQRS only when complexity is justified.

Common Interview Questions

What is CQRS?

CQRS (Command Query Responsibility Segregation) is an architectural pattern that separates write operations (commands) from read operations (queries), allowing each side to be optimized independently.


Why is CQRS used?

CQRS improves scalability, performance, and flexibility by allowing independent scaling of read and write workloads and enabling different data models for each.


Is CQRS eventually consistent?

Yes. In many implementations, the read model is updated asynchronously using events, so there can be a short delay before new data appears in read queries.


Can CQRS work without Event Sourcing?

Yes. CQRS and Event Sourcing are independent patterns. CQRS can use a traditional relational database for writes while maintaining a separate read model.


Which databases are commonly used with CQRS?

  • Write Model: PostgreSQL, MySQL, Oracle, SQL Server
  • Read Model: Redis, OpenSearch, Elasticsearch, MongoDB, Cassandra

Summary

CQRS is a powerful architectural pattern for enterprise applications with heavy read and write workloads. By separating commands from queries, it enables independent scaling, optimized data models, and improved application performance.

In this article, we covered:

  • CQRS fundamentals
  • Command and Query models
  • Read vs Write databases
  • Event-driven architecture
  • Kafka integration
  • Eventual consistency
  • Event Sourcing integration
  • Spring Boot architecture
  • Banking, Amazon, Netflix, and Uber examples
  • Monitoring
  • Best practices

CQRS is especially valuable for high-scale, cloud-native, event-driven systems. When combined with Kafka, Event Sourcing, and microservices, it enables applications to process millions of transactions while maintaining high performance and scalability.


Loading likes...

Comments

Share a question, correction, or practical insight about this article.

Loading approved comments...