Llegaste al límite. Tienes el query más optimizado que has escrito en tu vida: índices compuestos, particiones por fecha, CTEs anidados, vistas materializadas. Y aun así, ese reporte de balance financiero aparece en pantalla después de 20 minutos. Tu CEO lo abre cada lunes por la mañana. Cada lunes, un Slack o correo electrónico incómodo.
Este no es un problema de código. Es un problema de arquitectura. Y la buena noticia es que tiene solución —una solución que tiene nombre, historia y que hoy vive en producción en empresas desde startups hasta Amazon.
Se llama CQRS. Y hoy te cuento, ¿qué es y cómo funciona? Así se aplica en un sistema financiero real para lograr una mejora de más de 50 veces en el tiempo de respuesta de nuestros reportes críticos.
1. El problema real detrás del query lento
Antes de hablar de la solución, entendamos el problema correctamente. Porque no es solo que “el query es lento”.
Cuando tu base de datos supera los 100 GB, técnicamente estás en territorio de big data. Y el problema con big data no es almacenarlo; es que las bases de datos transaccionales tradicionales fueron diseñadas para una cosa muy específica, y esa cosa no es generar reportes analíticos sobre millones de registros históricos en tiempo real.
Lo que tu BD transaccional hace bien
Registrar una venta nueva al instante
Actualizar el saldo de un usuario
Buscar un registro exacto por ID
Garantizar que dos procesos no choquen (ACID)
Operaciones de milisegundos en filas individuales
Lo que te está pidiendo el negocio
Balance Sheet de los últimos 12 meses
Revenue por categoría, por región, por hora
Conciliaciones cruzando millones de transacciones
Reportes que unen 40+ tablas
Análisis sobre años de datos históricos
Estás forzando a tu base de datos a hacer algo para lo que no fue diseñada. Y el resultado es predecible: contención de locks, I/O saturado, timeouts y un reporte que tarda más que una reunión de roadmap.
La raíz del problema
Estás usando la misma base de datos para escribir operaciones transaccionales en tiempo real y para leer reportes analíticos masivos. Estas dos cargas de trabajo tienen necesidades radicalmente opuestas —y están peleando por los mismos recursos.
2. ¿Qué es CQRS?
CQRS son las siglas de Command Query Responsibility Segregation. En español: Segregación de responsabilidades entre comandos y consultas.
El concepto fue formalizado por el arquitecto de software Greg Young alrededor de 2010, inspirándose en el principio más simple de CQS (Command Query Separation) de Bertrand Meyer, que dice:
“Un método debería ser un comando que realiza una acción, o una consulta que retorna datos —nunca ambos.”
CQRS lleva esta idea al nivel arquitectónico. No solo separamos los métodos: separamos los modelos de datos, las bases de datos y los sistemas enteros según si su propósito es escribir o leer.
Un ejemplo practico
Imagina que tienes una sola caja registradora que sirve para cobrarles a los clientes y para generar el reporte contable de fin de mes. CQRS dice: usa una caja para cobrar (operaciones en vivo) y usa un sistema separado —optimizado para ello— para generar los reportes. Cada uno hace lo suyo, y los dos lo hacen mejor.
3. La analogía que lo explica todo
Piensa en un restaurante de alta rotación.
En la cocina, hay un sistema de comandas: cada mesero escribe el pedido, el chef lo ejecuta. Aquí la prioridad es velocidad, exactitud y consistencia. Si dos mesas piden el mismo plato, los pedidos no pueden mezclarse. Esto es el modelo de escritura: transaccional, secuencial, fuerte en garantías.
Ahora imagina que el dueño quiere saber cuál fue el plato más vendido el último trimestre, en qué mesa se genera más ticket promedio y a qué hora hay más rotación. Si le pregunta al chef en medio del servicio, el restaurante colapsa. Por eso existe la oficina del contador: toma los mismos datos (las comandas del día), los procesa en otro lugar y genera los reportes sin interrumpir la cocina.
CQRS es exactamente eso: la cocina sigue funcionando a máxima velocidad, y la oficina analítica trabaja con una copia de los datos —optimizada para responder preguntas complejas.
4. La arquitectura en detalle
Veamos cómo se ve esto en la práctica con el flujo completo de datos.
El lado de escritura: Commands
Todo lo que modifica el estado del sistema pasa por aquí. Un pago registrado, una factura emitida, un usuario actualizado. Estos son comandos: tienen intención clara y el sistema garantiza que se ejecutan correctamente, de forma atómica y consistente.
La base de datos de escritura es una BD transaccional clásica —típicamente PostgreSQL o MySQL. Está optimizada para escrituras rápidas, integridad referencial y concurrencia segura. Aquí viven tus garantías ACID.
El lado de lectura: Queries
Todo lo que solo consulta datos vive aquí. Un reporte de balance, el revenue por categoría, una conciliación histórica. Estas son consultas: no modifican nada —y necesitan hacerlo sobre grandes volúmenes de datos sin interferir con la operación.
La base de datos de lectura es una BD analítica, orientada a columnas —como ClickHouse, BigQuery, Redshift o DuckDB. Puede hacer en segundos lo que una BD transaccional haría en minutos, porque fue diseñada exactamente para eso.
El puente: Change Data Capture (CDC)
El mecanismo que mantiene ambas bases de datos sincronizadas se llama CDC. Cada vez que algo cambia en la BD de escritura, ese cambio se captura y se replica en la BD de lectura —en tiempo casi real, sin impactar el rendimiento del sistema principal.
¿Cómo funciona CDC técnicamente?
PostgreSQL, por ejemplo, mantiene un “diario de bitácora” llamado WAL (Write-Ahead Log). Antes de aplicar cualquier cambio, lo registra ahí. CDC conecta una herramienta (Debezium, AWS DMS, ClickPipes) a ese diario y transmite los cambios hacia la BD de lectura de forma continua. Es como fotocopiar cada comanda antes de enviarla a cocina.
5. Un caso real: de 27 minutos a 30 segundos
Trabajando en un sistema core bancario de puntaje crediticio, nos encontramos con este problema de frente. El reporte de Balance Sheet cruzaba decenas de tablas y agregaba años de datos históricos sobre una base de datos PostgreSQL que también estaba sirviendo todas las operaciones transaccionales en vivo.
Tiempo de generación antes de CQRS: 27 minutos.
27 min antes — OLTP solo
30 seg después — CQRS
54× en mejora de performance
La solución fue implementar CQRS sobre la infraestructura existente: replicar las tablas relevantes hacia una base de datos analítica columnar mediante CDC y redirigir las consultas de reportes para que se ejecutaran ahí —sin tocar el sistema de escritura ni el código de negocio.
Resultado en producción
El Balance Sheet que tardaba 27 minutos ahora carga en 30 segundos. La instancia transaccional dejó de saturarse con queries analíticos. Los desarrolladores del equipo pueden ejecutar consultas ad hoc sin riesgo de bloquear la operación. Y el reporte que el C-Level necesitaba cada lunes dejó de ser motivo de conversación incómoda.
El tipo de query que cambió todo
-- La misma query. Diferente motor. Eso es CQRS.
SELECT
account_id,
sum(debit) AS total_debit,
sum(credit) AS total_credit,
sum(debit - credit) AS balance
FROM account_move_line
WHERE date >= '2024-01-01'
AND company_id = 1
GROUP BY account_id
ORDER BY account_id;
-- En PostgreSQL (OLTP): ~27 minutos
-- En BD columnar (OLAP): ~30 segundosEl query no cambió una sola línea. Lo que cambió fue sobre qué motor corría.
6. ¿Cuándo sí y cuándo no aplicar CQRS?
CQRS no es una bala de plata. Es una herramienta poderosa con un costo real de complejidad operacional. Usarla mal puede crearte más problemas de los que resuelve.
✓ Úsalo cuando...
Tus reportes tardan más de lo aceptable y optimizar el query ya no ayuda
Tu BD transaccional se satura cuando alguien ejecuta un reporte pesado
Tienes más de ~50–100 GB de datos con crecimiento constante
Los patrones de lectura y escritura son radicalmente distintos
Puedes tolerar datos con un pequeño delay (segundos o minutos)
Tienes capacidad para operar y monitorear dos bases de datos
✗ No lo uses cuando...
Tu app es simple y tu BD es menor de 10–20 GB
Necesitas consistencia instantánea al 100% en todo momento
Tu equipo no tiene experiencia en sistemas distribuidos
Estás en etapa de validación de producto (premature optimization)
No tienes observabilidad para detectar problemas de sincronización
El costo real de implementación
Pagas con consistencia eventual: hay un pequeño delay entre que algo se escribe en la BD transaccional y cuando aparece en la BD de lectura. Para reportes históricos o analíticos, esto es completamente aceptable. Para un saldo en tiempo real que mueve dinero en producción, puede no serlo. Conoce tu caso de uso antes de decidir.
7. ¿Cómo empezar sin romper producción?
La belleza de CQRS es que puedes adoptarlo incrementalmente. No necesitas reescribir tu sistema. El camino de menor riesgo:
Identifica tu candidato piloto. El query más lento, más crítico, con mayor impacto en el negocio. Ese es tu punto de entrada.
Levanta una BD analítica. ClickHouse, BigQuery, Redshift, DuckDB: los managed services reducen la operación inicial a casi cero. Empieza con una instancia pequeña.
Configura el pipeline CDC. Debezium, AWS DMS, ClickPipes, Airbyte. Replica solo las tablas que necesita tu query piloto — no toda la BD de golpe.
Redirige ese único query. El resto de tu sistema no cambia. Solo el reporte piloto apunta a la BD de lectura.
Mide y valida. Compara tiempos. Verifica que los datos coinciden entre ambas bases. Documenta el delta de sincronización.
Expande gradualmente. Agrega más queries y más tablas según el ROI real que vayas viendo. No migres todo de una vez.
Ejemplo, para que me entiendas
La migración incremental reduce el riesgo a casi cero. En ningún paso modificas el sistema de escritura ni tocas la fuente de verdad. El rollback es trivial: si algo falla en la BD de lectura, simplemente vuelves a apuntar el query al sistema original. Es una de las pocas apuestas arquitectónicas donde el downside está completamente acotado.
En mi experiencia
Si tu reporte tarda 20 minutos, el problema no es el query. El problema es que estás usando una herramienta de construcción para hacer trabajo de análisis. CQRS es el reconocimiento arquitectónico de que leer y escribir son problemas fundamentalmente diferentes —y merecen herramientas diferentes.
No es magia. Es separación de responsabilidades aplicada a escala de datos. Y cuando lo ves funcionar —cuando ese reporte que torturaba los lunes de tu C-Level o Stakeholder aparece en 30 segundos— entiendes por qué es uno de los patrones más influyentes de la ingeniería de software moderna.
El siguiente paso es tuyo. Identifica ese query e identifica de qué tabla o base de datos estamos hablando. Empieza pequeño. Mide todo; eso te ayudará a dar una idea si el escalamiento necesita segregación de responsabilidades o simple optimización.
¿Tienes preguntas?
Si estás evaluando implementar CQRS en tu stack —sea cual sea el motor analítico que consideras— deja tu pregunta en los comentarios. En el próximo artículo entro a los detalles de configurar CDC desde PostgreSQL: el WAL, los replication slots y los gotchas que nadie te cuenta hasta que estás en producción.




