---
title: "CQRS"
type: "architectural-pattern"
slug: "cqrs"
url: "http://localhost:3000/es/architectural-patterns/cqrs.md"
also_known_as: "Command Query Responsibility Segregation"
description: "Separa el modelo que cambia el estado (comandos) del modelo que lee el estado (consultas), de modo que cada lado pueda modelarse, escalarse y optimizarse de forma independiente."
languages: ["typescript"]
---
# CQRS

_Also known as: Command Query Responsibility Segregation_

> Separa el modelo que cambia el estado (comandos) del modelo que lee el estado (consultas), de modo que cada lado pueda modelarse, escalarse y optimizarse de forma independiente.

## Intent

Usa un modelo para actualizar la información y un modelo distinto para leerla. Los comandos expresan la intención de cambiar el estado; las consultas devuelven datos con la forma adecuada para mostrarlos. Ambos ya no tienen que llegar a un compromiso en torno a una única representación compartida.

## Problem

En un diseño tradicional, un mismo modelo sirve tanto para las escrituras como para las lecturas. Las escrituras necesitan validación e invariantes ricos; las lecturas necesitan formas desnormalizadas y listas para mostrar, a menudo muchas distintas para diferentes pantallas e informes.

Forzar ambos a través de los mismos objetos y tablas conduce a compromisos incómodos: sobreobtención de datos (over-fetching), mapeos ORM complejos, contención de bloqueos y un modelo que no es bueno en ninguna de las dos tareas.

## Solution

CQRS divide el sistema en dos. El **lado de escritura** gestiona los _comandos_ mediante manejadores que cargan un agregado, imponen invariantes y persisten el cambio (emitiendo eventos opcionalmente). El **lado de lectura** sirve _consultas_ desde uno o varios _modelos de lectura_ con una forma diseñada específicamente para las vistas que los consumen.

Ambos lados pueden compartir una base de datos o usar almacenes separados. Cuando están separados, los modelos de lectura se mantienen actualizados proyectando los eventos del lado de escritura, aceptando la _consistencia eventual_ a cambio de un escalado independiente y consultas más simples.

## Structure

* **Comando** — una solicitud para cambiar el estado, nombrada según su intención (`PlaceOrder`).
* **Manejador de comandos** — valida y aplica el comando al modelo de escritura.
* **Modelo de escritura** — agregados que imponen invariantes; pueden emitir **eventos**.
* **Modelo de lectura / proyección** — vistas desnormalizadas construidas para las consultas, actualizadas a partir de eventos.
* **Consulta** & **manejador de consultas** — solicitudes de solo lectura servidas desde el modelo de lectura.

## Applicability

* Úsalo donde **las lecturas y las escrituras tengan formas o cargas muy diferentes**: muchas vistas de lectura, generación intensiva de informes o una proporción de lecturas frente a escrituras elevada.
* Úsalo para **interfaces basadas en tareas** y dominios colaborativos, donde se combina de forma natural con el diseño guiado por el dominio (DDD) y el event sourcing.
* **Evítalo** para un CRUD sencillo; un único modelo es más simple y la separación añade coste sin recompensa.

## How to Implement

1. Modela los **comandos** como intenciones explícitas en lugar de actualizaciones genéricas.
2. Encamina cada comando a un **manejador** que cargue el agregado pertinente e imponga sus invariantes.
3. Persiste el cambio y, si usas eventos, **publica** lo que ocurrió.
4. Construye **modelos de lectura** adaptados a tus vistas; si están separados, actualízalos proyectando eventos.
5. Sirve las **consultas** directamente desde los modelos de lectura: nada de lógica de dominio en el lado de lectura.

## Pros

* Los lados de lectura y escritura pueden modelarse, optimizarse y escalarse de forma independiente.
* Cada modelo se mantiene pequeño y centrado en una sola tarea.
* Encaja con las interfaces basadas en tareas y se compone bien con el event sourcing y el DDD.
* Los modelos de lectura pueden adaptarse por vista, eliminando joins incómodos.

## Cons

* Más piezas móviles y más código que un único modelo CRUD.
* Los almacenes de lectura separados introducen consistencia eventual, que la experiencia de usuario debe gestionar.
* Es fácil caer en la sobreingeniería; rara vez se justifica en dominios sencillos.
* Sobrecarga operativa de las proyecciones y de la fontanería de mensajes.
## Relations

**Related patterns**

- [Diseño guiado por el dominio](/es/architectural-patterns/domain-driven-design.md)

## Code Examples

### typescript

```typescript
// Lado de escritura: un comando y su manejador.
type PlaceOrder = { orderId: string; sku: string; qty: number }

class PlaceOrderHandler {
  constructor(private orders: OrderRepository) {}
  async handle(cmd: PlaceOrder) {
    const order = new Order(cmd.orderId)
    order.addLine(cmd.sku, cmd.qty)
    await this.orders.save(order) // emite OrderPlaced
  }
}

// Lado de lectura: una consulta servida desde una vista desnormalizada.
type GetOrderSummary = { orderId: string }

class GetOrderSummaryHandler {
  constructor(private views: OrderSummaryView) {}
  handle(q: GetOrderSummary) {
    return this.views.byId(q.orderId) // con la forma adecuada para la pantalla
  }
}
```

