Skip to content
webkida wiki
Go back

【System Design】 CQRS (Command Query Responsibility Segregation)

A walkthrough of CQRS — splitting commands (writes) from queries (reads) — compared with ordinary replication

Writes and reads differ in how they behave and in how load grows. CQRS (Command Query Responsibility Segregation) is an architecture pattern that treats these two separately. The goal is to raise performance and scalability.

I split commands (writes) and queries (reads), then look at what is different compared with ordinary replication.

Terms

CQRS

Command Query Responsibility Segregation. You split write and read responsibilities and optimize them on separate data models or databases.

Command / query

A command is a write. A query is a read. CQRS separates these two clearly.

Eventual consistency

The data will be consistent in the end, but at a given moment it may be inconsistent. That is the premise. In CQRS, sync often becomes asynchronous, so this premise usually comes with it.

Replication

A mechanism that copies data from a master DB to a slave DB. The table structure is the same. The main goal is better read performance.

Event sourcing

A way to sync data from the write DB to the read DB. The write side is sometimes treated as an append-only history table.

CQRS

In the cloud, it is natural to scale each resource to the load. Writes and reads have different processing characteristics. In a cloud-native app, CQRS becomes a natural way to think. There is an explanation that simple CRUD (the same DB for writes and reads) becomes the exception pattern.

With CQRS you can scale independently and define a schema for each side. You can use the properties of the cloud. The aim is to keep complex business logic under control, reduce load on the system as a whole, and make it easier to extend.

Data consistency, though, becomes eventual consistency. At a given moment the data may be inconsistent. You do not have to put it on the whole system. You can design it flexibly, such as introducing it on only part of the system.

Comparison with replication

Compared with the usual replication design, the differences are as follows.

CQRSReplication
DB definition / data modelDifferent for writes and readsThe same for writes and reads
Performance optimizationOptimize writes and reads separatelyImprove read performance
Data sync timing
Data consistency
Asynchronous
Eventual consistency
Real-time sync
Implementation costMessyRelatively easy

DB definition / data model

In CQRS, the update DB and the read DB generally have different table structures. The write DB is normalized to keep consistency. The read DB is denormalized to raise query performance.

In replication, the master DB for updates and the slave DB for reads basically have the same table structure. Data written to the master is copied to the slave, and the slave is mostly read-only. The table design itself is the same. Improving query performance often depends on index optimization and caching.

Table structures for CQRS and replication

Figure: CQRS uses different table structures for writes and reads. Replication copies the same structure.

Performance optimization

CQRS fully separates writes and reads and optimizes each for its use. Writes emphasize data consistency and transaction management. You usually write efficiently on a normalized DB. Reads maximize query performance with a denormalized data model. You can design both sides to be optimized.

Replication is mainly aimed at better read performance. Slaves take the read-only load. The master’s burden goes down, and overall read performance goes up. Writes happen only on the master, so write performance is not optimized. Because you duplicate the same DB structure, it is specialized for strengthening reads.

Data sync timing / data consistency

In CQRS, writes and reads use different DBs, so sync is generally asynchronous. There can be a time lag before what you wrote shows up on the read side. It becomes consistent in the end, but you cannot always get the latest data in real time. Going asynchronous raises scalability and lets you use a data model optimized for reads and one optimized for writes. On the other hand, you have to account for temporary inconsistency.

In replication, writes to the master are copied to the slave in real time, or almost real time. The slave is read-only and spreads the load. It is designed so the slave keeps strong consistency with the master. Replication lag can still produce a small gap. Even so, it is an effective way to raise read performance while keeping consistency at a high level.

Implementation cost

Implementation cost tends to be higher for CQRS.

Because you fully separate writes and reads, you have to design different data models and architectures for each. The system as a whole becomes more complex. You manage the write DB and the read DB separately, so you need infrastructure design and operations, plus a way to sync asynchronously. Both development cost and operations cost go up. Source code is also generally split between writes and reads. You need development, test, and maintenance resources for each.

Replication implementation cost is relatively low. It is a mechanism that copies an existing DB structure, so there is little new design or development. If you use the replication feature the DBMS provides, setup and management are relatively easy. You can keep the design simple. Development and maintenance cost is lower than CQRS.

Takeaways

CQRS is a pattern that splits commands (writes) and queries (reads) and uses a data model or DB optimized for each. You can scale independently and use the properties of the cloud. Eventual consistency is the premise. If a requirement cannot accept that, you cannot introduce it. You can also introduce it on only part of the system instead of the whole thing.

Replication is a technique that copies the same table structure to raise read performance. It is easier to implement than CQRS, but it does not optimize the write side or separate the schemas.

Related to this is event sourcing. You do not allow updates on the write DB; you treat it as an append-only history table. You sync that content to the read DB. This explanation of event sourcing is easy to follow.


Share this post:

Previous Post
【Claude Code】 How to work around Auto-update failed
Next Post
Transaction isolation levels