Databases Practical By Samson Tanimawo, PhD Published Jun 25, 2025 4 min read

CQRS Pattern

Read/write separation.

CQRS in plain terms

Command-Query Responsibility Segregation: separate paths for writes (commands) and reads (queries). Different models, different stores, different scaling.

Writes go through a single canonical model that enforces business rules. Reads come from optimised projections built from the write log.

Sounds elegant; adds significant complexity. Justified when read and write workloads diverge enough that a unified model becomes a bottleneck.

When CQRS pays

Read-heavy workloads with complex queries: e-commerce product catalogue, analytics dashboards. Reads are 100x writes; specialised read models help.

Different consistency requirements. Writes need strict consistency; reads can tolerate eventual consistency for performance.

Audit and event-sourcing requirements. CQRS pairs naturally with event sourcing: commands produce events; events build read projections.

When not

CRUD applications without complex query needs. Adding CQRS to a simple form-and-database app multiplies complexity for marginal benefit.

Small teams or early-stage products. The operational burden of multiple models, sync mechanisms, and eventual consistency is real.

When eventual consistency is unacceptable. Some domains need read-after-write strict consistency; CQRS makes this harder.

Implementation patterns

Single database with separate read replicas: lightweight CQRS. Writes to primary; reads from replicas. Eventual consistency at replication lag.

Separate stores: Postgres for writes, Elasticsearch for reads. Async pipeline syncs. Heavier but more flexible.

Event-sourced CQRS: write log as the canonical store, projections built by replaying events. Most complex, most powerful.

Operating CQRS

Read projection lag is a first-class metric. SLO on lag; alerting when it grows.

Replay capability for projections. When a projection bug ships, replay from the event log to rebuild.

Schema migration for read models is independent from writes. Versioning and migration strategies needed for each.