Patrón de diseño CQRS: cuándo usarlo y por qué no es para todos
Tiempo estimado de lectura: 4 min
Ideas clave
- Separa escritura (Commands) y lectura (Queries) para optimizar modelos y almacenamiento.
- Beneficia escalado de lecturas y vistas especializadas, pero introduce consistencia eventual y complejidad operativa.
- Úsalo cuando el ratio lectura/escritura sea muy alto o el dominio requiera vistas múltiples o reglas complejas.
¿Quieres escalar lecturas sin romper transacciones? El patrón de diseño CQRS te puede salvar —o hundir— dependiendo de cómo lo uses. Aquí tienes la guía técnica, sin adornos, con ejemplos y criterios claros para decidir.
En las primeras líneas: el patrón de diseño CQRS separa explícitamente escritura (Commands) y lectura (Queries). Esa separación permite optimizar cada lado con un modelo y almacenamiento distinto, pero introduce consistencia eventual y complejidad operativa.
Resumen rápido (lectores con prisa)
CQRS separa operaciones que modifican estado (Commands) de las que leen datos (Queries).
Úsalo cuando necesites escalado de lecturas, vistas desnormalizadas o múltiples proyecciones por consumidor.
Introduce consistencia eventual y mayor complejidad operativa (event bus, idempotencia, reintentos).
Implementación típica: write model ACID + event bus + proyectores + read model optimizado.
Patrón de diseño CQRS: ¿qué es y cómo funciona?
CQRS (Command Query Responsibility Segregation) extiende el principio CQS de Bertrand Meyer a nivel arquitectónico. La idea es sencilla:
- Commands = intenciones que cambian estado (ej. CrearPedido).
- Queries = lecturas sin efectos secundarios (ej. ObtenerPedidosUsuario).
Arquitectura típica
- Lado de escritura: valida reglas de negocio, persiste en DB normalizada (ACID) y publica eventos.
- Bus de eventos: Event bus recomendado (Kafka, RabbitMQ o SQS transportan los eventos).
- Proyectores (projectors): consumen eventos y actualizan vistas desnormalizadas.
- Lado de lectura: lee desde vistas optimizadas (Elasticsearch, MongoDB, Redis).
Referencia conceptual: Referencia conceptual
Ejemplo práctico (TypeScript, simplificado)
Command side
Command side:
class CrearPedidoCommand { constructor(public usuarioId:string, public items:any[]){ } }
class PedidoHandler {
async execute(cmd: CrearPedidoCommand){
const pedido = PedidoFactory.crear(cmd);
await writeRepo.save(pedido); // BD transaccional
eventBus.publish(new PedidoCreadoEvent(pedido.id, pedido.snapshot()));
}
}
Query side (proyector)
Query side (proyector):
eventBus.subscribe('PedidoCreado', async (evt) => {
await readRepo.upsert({ id: evt.pedidoId, usuarioId: evt.usuarioId, total: evt.total });
});
La UI consume readRepo: consultas rápidas, sin joins.
Por qué usar CQRS: beneficios reales
- Escalado independiente: replicas de lectura que soportan millones de consultas sin tocar la base transaccional.
- Consultas ultrarrápidas: vistas pre-agg y desnormalizadas adaptadas a cada cliente.
- Lógica de dominio limpia: los comandos alojan reglas complejas sin ensuciar las consultas.
- Seguridad y límites: segmentas permisos entre escritura y lectura.
Stack sugerido
- Comandos: NestJS + PostgreSQL
- Event bus: Kafka
- Lectura: Elasticsearch/OpenSearch o Redis para vistas calientes
- Frameworks: Axon (Java) para Event Sourcing/CQRS
El coste: por qué no es para todos
CQRS trae dos impuestos que muchos subestiman:
- Consistencia eventual. Tras un comando exitoso, la vista puede tardar en actualizarse. La UI y procesos deben tolerar ese lag (read-your-writes, polling, optimistic updates).
- Complejidad operativa. Monitoreo del bus, reintentos, idempotencia, versionado de eventos, proyecciones huérfanas. Debuggear fallos distribuidos se vuelve un arte oscuro.
Señales de alarma: equipo pequeño, dominio CRUD simple, SLA que exige consistencia inmediata. En esos casos, CQRS es over-engineering.
Cuándo aplicarlo (criterios claros)
Usa CQRS solo si encajan al menos dos de estos casos:
- Ratio lectura/escritura muy alto (p. ej. 100:1 o más).
- Vistas múltiples y complejas que requieren pre-agrupación o formato distinto por consumidor.
- Dominio con reglas de negocio complejas que complican las consultas si se mezclan.
- Ya trabajas con arquitectura basada en eventos o Event Sourcing.
Evítalo si:
- Tu app es formularios + listados simples.
- Tienes requisitos de consistencia inmediata estrictos.
- No hay capacidad operativa para mantener infra distribuida.
Migración práctica: cómo empezar sin detonarte
- Identifica el “hot path” de lecturas lentas (métricas p95/p99).
- Implementa un proyector que consuma eventos y mantenga una vista materializada mínima.
- Redirige esas consultas al read model gradualmente.
- Añade pruebas de integridad, idempotencia y observabilidad en el event bus.
- Solo entonces extiende el patrón a otros contextos.
Herramientas útiles: Axon, EventStore, Kafka, y librerías CQRS como @nestjs/cqrs.
Conclusión y siguiente paso
El patrón de diseño CQRS te da independencia y rendimiento donde el modelo CRUD choca contra límites reales. Pero es cirugía mayor: pagas con latencia, operaciones y debugging distribuido. No lo adoptes por moda; adopta CQRS por necesidad demostrada.
Empieza pequeño: crea una proyección, mide el lag, valida la experiencia de usuario. En el próximo artículo mostraré una migración paso a paso desde un endpoint CRUD hacia una vista materializada con Kafka y un proyector en Node.js.
FAQ
¿Qué significa CQRS?
CQRS es la segregación de responsabilidades entre Commands (operaciones que modifican estado) y Queries (operaciones de lectura sin efectos secundarios).
¿Cuándo es una buena idea implementarlo?
Cuando tienes un ratio de lectura/escritura muy alto, múltiples vistas que requieren pre-agrupación o un dominio con reglas complejas que dificultan mezclar lectura y escritura en el mismo modelo.
¿Qué impacto tiene en la consistencia de datos?
Introduce consistencia eventual: tras un comando exitoso las vistas pueden tardar en reflejar el cambio. La UI y procesos deben manejar ese lag explícitamente.
¿Qué componentes operativos debo considerar?
Monitoreo del bus de eventos, manejo de reintentos, idempotencia, versionado de eventos, y la salud de las proyecciones son claves para operar CQRS en producción.
¿Puedo aplicar CQRS solo a partes de mi sistema?
Sí. Es recomendable empezar por un “hot path” de lecturas lentas y migrar gradualmente a una vista materializada antes de ampliar el patrón.
¿Qué herramientas ayudan con CQRS y Event Sourcing?
Herramientas mencionadas incluyen Kafka, Axon, EventStore y librerías como @nestjs/cqrs, así como bases de datos optimizadas para lectura como Elasticsearch o Redis.

Leave a Reply