Introduction
While developing APIs, I always strive to ensure that responses are returned within 200ms. But guess what? Sticking to that principle is one of the toughest tasks I have faced. And then, the hell broke loose when I was working on an API for an eCommerce platform to fetch order summaries.
The API had to fetch data from six tables spread across five microservices, each handling millions of records. Even with extensive optimizations, keeping the response time under 200ms was impossible due to the architecture.
And that’s when I discovered the CQRS (Command Query Responsibility Segregation) pattern a game-changer that helped me achieve my performance goals. I fell in love with it, and today, I am sharing my experience so you can also harness its power.
Let’s start with the definition before diving into the magic of CQRS pattern.
What is CQRS (Command Query Responsibility Segregation)?
CQRS (Command Query Responsibility Segregation) is a software architecture pattern that separates read operations (queries) from write operations (commands). Instead of having a single model to handle both, CQRS introduces separate models:
- Command Model: Handles writes (Create, Update, Delete operations) and enforces business rules.
- Query Model: Handles reads (Fetch operations) and is optimized for performance.
- Event Bus: Ensures that updates in the command model are eventually reflected in the query model asynchronously.
By decoupling reads and writes, CQRS allows APIs to be significantly faster because queries no longer depend on complex joins or transactional integrity constraints.
CQRS Query Models & Event Bus
Here’s how the CQRS pattern works in a distributed system:
- Write operations update the Command Model (SQL Database mircoservices).
- An Event Bus publishes events whenever data changes (e.g., Order Placed, Payment Processed, etc.).
- The Query Model (No SQL Database microservice) listens to these events and updates a denormalized, optimized version of the data.
- Read operations now use this optimized Query Model, allowing for fast retrieval without expensive joins



Now, let’s see CQRS in action with an eCommerce order summary API.
CQRS Example in an eCommerce Platform
The Problem
In a traditional approach, fetching an order summary required joining data from six different tables across multiple microservices:
- Users (Customer Details)
- Orders (Order Metadata)
- OrderItems (Products in the Order)
- Payments (Payment Status)
- Shipping (Delivery Information)
- Products (Product Details)
Since each microservice had its own database, the API had to make multiple requests and perform heavy joins, leading to slow performance.
How CQRS Helped
With CQRS, we built a denormalized Order Summary Table in the Read Model. This table is updated asynchronously whenever an order is created or updated. Now, instead of fetching data from multiple microservices, the API can fetch everything from one optimized table.
Write Model (Command Side)
Table for Writes (Normalized Data Structure)



Read Model (Query Side)
Denormalized Order Summary Table



API Response After CQRS Pattern
{
"orderId": "1234",
"user": {
"name": "John Doe",
"email": "john@example.com"
},
"totalAmount": 899.99,
"status": "Shipped",
"products": [
{ "productId": "p1a2b3c4", "name": "Smartphone", "quantity": 1, "price": 699.99 },
{ "productId": "p9x8y7z6", "name": "Wireless Earbuds", "quantity": 1, "price": 199.99 }
],
"paymentStatus": "Completed",
"shippingStatus": "In Transit",
"trackingNumber": "TRK123456789"
} How CQRS Pattern Makes the API Faster
- No more heavy joins → API fetches everything from a precomputed read table.
- No dependency on multiple microservices → One optimized query instead of multiple API calls.
- Asynchronous updates → Event Bus ensures data stays eventually consistent without blocking API performance.
Key Benefits of CQRS Pattern
Performance Boost
- No complex joins → Faster response times (~<200ms response achieved).
- Read models are optimized for fast retrieval.
Scalability
- Reads and writes scale independently, allowing microservices to handle high traffic efficiently.
- Command-side databases remain normalized, ensuring data integrity.
Flexibility
- Read models can be designed for specific use cases (e.g., Order Summary API).
- Different databases (SQL, NoSQL, etc.) can be used for command and query models.
Challenges & Considerations
Eventual Consistency
- Since reads are updated asynchronously, there may be a lag before changes reflect.
- If real-time consistency is needed, CQRS alone may not be enough.
Increased Complexity
- Maintaining two models (Command & Query) adds extra code & infrastructure overhead.
- Requires event-driven architecture (Kafka, RabbitMQ, or AWS SNS/SQS).
Data Synchronization
- Event-driven updates must be reliable to prevent stale read models.
- Monitoring & logging are crucial for tracking CQRS events.
Conclusion
CQRS completely transformed my eCommerce API performance, making it blazing fast . If you’re struggling with slow APIs due to heavy joins & microservice calls, give CQRS a try—it might be your performance savior too!



























