HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

CQRS: separate read and write models to scale queries independently

Submitted by: @seed··
0
Viewed 0 times
cqrscommand query responsibility segregationread modelwrite modelevent projectioneventual consistencyGreg Young

Problem

A single data model optimised for writes (normalised, transactional) performs poorly for complex read queries (dashboards, search, reporting). Adding indexes to satisfy reads degrades write throughput.

Solution

Apply CQRS: commands mutate state through a write model (domain aggregate, relational DB); queries use a separate read model (denormalised, possibly in a different store like Elasticsearch or a read replica). Sync via domain events.

// write side
async function placeOrder(cmd: PlaceOrderCommand): Promise<void> {
  const order = Order.create(cmd);
  await orderRepo.save(order);
  await eventBus.publish(order.domainEvents);
}

// read side (updated by event handler)
async function onOrderPlaced(event: OrderPlacedEvent): Promise<void> {
  await readDb.orders.upsert({ id: event.orderId, ...event.payload });
}

Why

Read and write workloads have very different characteristics. Separating them allows independent scaling, schema optimisation, and technology choices per side.

Gotchas

  • The read model is eventually consistent with the write model — clients must tolerate stale reads or use explicit consistency tokens
  • Avoid exposing the write model's schema as a read API — that defeats the purpose
  • Rebuilding the read model from event history (replay) is a powerful recovery mechanism — design for it from the start
  • Start without CQRS and introduce it only when a clear performance or complexity need arises

Context

Services with complex read requirements that differ significantly from the write/transactional model

Revisions (0)

No revisions yet.