Arquitectura de eventos y mensajería asíncrona a medida
Hay un momento en la vida de toda aplicación a medida en el que el monolito empieza a doler. Las llamadas síncronas se vuelven lentas, un servicio caído tumba a tres más y cada nueva funcionalidad obliga a tocar código que llevaba dos años tranquilo. Cuando llegas ahí, lo siguiente que pruebas casi siempre es lo mismo: desacoplar con eventos y mensajería asíncrona.
Te cuento cómo planteo este tipo de arquitectura cuando la diseño desde cero o cuando entro a rescatar un proyecto que cruje. RabbitMQ, Kafka, CQRS, event sourcing y los patrones que de verdad usamos en producción.
Qué es la arquitectura orientada a eventos
Una arquitectura orientada a eventos (EDA) sustituye las llamadas directas entre componentes por la emisión y consumo de mensajes. Un evento es un hecho que ya ha ocurrido: "pedido confirmado", "pago rechazado", "usuario dado de baja". Tu sistema deja de preguntar y empieza a contar lo que pasa.
El cambio de paradigma
En el modelo clásico, el servicio A llama al B, espera y reza para que responda. Si B está caído, A se atasca. Y si mañana aparece un servicio C que también quiere reaccionar, te toca volver al código de A y enchufarlo.
Con eventos, A solo grita al aire: "esto ha pasado". B y C escuchan si les interesa y reaccionan a su ritmo. Ese desacoplamiento es la diferencia entre una aplicación que puedes evolucionar durante años y otra que toca reescribir cada dos.
Componentes fundamentales
Tres piezas: productores (publican eventos), consumidores (se suscriben y reaccionan) y el broker de mensajería, que hace de cartero. Cada pieza vive su vida, se despliega cuando le toca y escala según su carga.
Brokers de mensajería: RabbitMQ y Apache Kafka
Elegir broker es la decisión técnica más cara de revertir aquí. Si te equivocas, no cambias una librería: rediseñas la columna vertebral. Los dos que veo en producción una y otra vez son RabbitMQ y Apache Kafka, y resuelven problemas distintos.
RabbitMQ
RabbitMQ implementa AMQP y trabaja con un modelo de colas que la mayoría de los equipos pillan en una tarde. Publicas en un exchange, ese exchange enruta a una o varias colas según las reglas que defines, y los consumidores van leyendo.
Su fortaleza está en la flexibilidad de enrutamiento: direct, fanout, topic y headers. En la práctica significa que puedes montar flujos complejos sin escribir código de routing en tus servicios. La lógica vive en la infraestructura.
Lo uso casi siempre en el clásico de tareas en background y notificaciones. Pongamos una plataforma de reservas: el usuario confirma, sueltas un evento y se reparte en cuatro colas (email, SMS, push y registro analítico). Cada una la consume un worker distinto, y si el de SMS se cae media hora, los otros tres siguen como si nada.
Apache Kafka
Kafka juega en otra liga. En vez de colas tiene un log distribuido organizado por topics y particiones, y los mensajes se persisten en disco el tiempo que tú decidas. Eso permite algo imposible con RabbitMQ: que un consumidor nuevo entre mañana y se lea los eventos de la semana pasada para reconstruir su estado.
Donde Kafka brilla es en volumen y streaming. Millones de mensajes por segundo con latencias por debajo de los 10 ms si el cluster está bien dimensionado. Tiene sentido en pipelines de datos, telemetría IoT, integraciones con data lakes o cualquier escenario donde quieras alimentar varios sistemas downstream desde la misma fuente.
Cuándo elegir cada uno
Mi regla: si el volumen es moderado (unos miles de mensajes por segundo), necesitas enrutamiento sofisticado y quieres simplicidad operativa, RabbitMQ. Si manejas decenas de miles por segundo, necesitas retención larga o vas a hacer stream processing en serio, Kafka.
Y no es raro que convivan los dos: Kafka como bus de eventos del dominio, RabbitMQ para colas de trabajo. Funciona.
CQRS: separar lecturas de escrituras
CQRS (Command Query Responsibility Segregation) propone algo que parece de cajón: separar el modelo que escribe del modelo que lee. Una API para comandos, otra para consultas. Dos caminos, dos formas de optimizar.
Cómo funciona CQRS
El lado de comandos recibe las escrituras: crear pedido, actualizar precio, cancelar suscripción. Cada comando se valida, se ejecuta y genera eventos que cuentan lo que ha pasado.
El lado de consultas mantiene vistas pensadas para leer. Se actualizan de forma asíncrona consumiendo los eventos del lado de escritura, y cada una vive en la tecnología que mejor le siente: PostgreSQL para informes, Elasticsearch para búsqueda full-text, Redis para listados que tienen que responder en menos de 5 ms.
Beneficios para aplicaciones a medida
Modelas las lecturas como el negocio las pide, sin contorsionar el modelo de escritura para veinte consultas distintas. Y escalas cada lado por su cuenta: si recibes 50 lecturas por escritura (normal en un SaaS), añades réplicas sin tocar el camino crítico.
Aviso: CQRS no es gratis. Duplica modelos, mete asincronía entre escribir y leer lo que acabas de escribir, y obliga al equipo a pensar en eventual consistency. Si tu aplicación tiene poca carga, complicas la vida sin ganar nada.
Event sourcing: el historial completo como fuente de verdad
Event sourcing es el compañero natural de CQRS. La idea es radical: en vez de guardar el estado actual de una entidad, guardas la secuencia de eventos que la han llevado hasta ese estado.
El principio fundamental
Imagina una cuenta bancaria. En el modelo clásico, una fila dice "saldo: 1.500 euros". Con event sourcing guardas la historia: cuenta abierta, ingreso de 2.000, cargo de 300, ingreso de 150, cargo de 350. El saldo no es un dato, es el resultado de reproducir esa secuencia.
Ventajas de event sourcing
Lo primero, trazabilidad total. Cada cambio queda registrado con su marca temporal, causa y contexto. Para sectores regulados (fintech, salud, legaltech) no es un nice-to-have, es un requisito que el regulador te va a pedir.
Lo segundo, puedes reconstruir el estado en cualquier punto del pasado. ¿Cómo estaba la cartera de un cliente el 14 de marzo a las 17:30? Reproduces los eventos hasta esa fecha y lo tienes. Imposible con un CRUD clásico salvo que mantengas histórico paralelo.
Lo tercero, flexibilidad para nuevas proyecciones. El negocio te pide una vista nueva: creas la proyección, le pasas los eventos históricos por encima y la tienes poblada. Sin scripts de migración ni ETLs a las tres de la madrugada.
Consideraciones prácticas
El error que más veo con event sourcing es aplicarlo a todo el dominio porque suena bien. Mal asunto. Añade complejidad real: el almacén crece sin parar (toca snapshots), la evolución del esquema tiene que mantener compatibilidad hacia atrás durante años, y el equipo necesita semanas para dejar de razonar en CRUD. Aplícalo solo en los agregados donde la auditoría aporta valor claro.
Casos de uso en aplicaciones a medida
Plataformas de comercio electrónico
Un e-commerce a medida es de los terrenos donde mejor se ve el beneficio. Cuando un cliente confirma una compra, sueltas un evento "pedido confirmado" y cada servicio reacciona por su cuenta: inventario reserva unidades, pagos llama a Redsys o Stripe, logística programa el envío con Seur o MRW. Si Redsys tarda 8 segundos un día tonto, el resto del flujo no se entera.
Sistemas de gestión empresarial
En un ERP a medida, la mensajería asíncrona permite que módulos que evolucionan a distinto ritmo convivan sin pisarse. Facturación puede recibir una actualización mensual mientras contabilidad lleva año y medio sin tocarse, siempre que respeten el contrato de eventos. Equipos en paralelo sin chocar.
Aplicaciones IoT y monitorización
Cuando recibes datos de cientos o miles de sensores, una arquitectura síncrona se cae. Kafka con streaming (Flink, Kafka Streams o ksqlDB) te permite ingerir, transformar y reaccionar en tiempo real, generando alertas y guardando histórico. Tengo clientes moviendo 200.000 eventos por segundo con un cluster Kafka de tres nodos sin despeinarse.
Integraciones con sistemas externos
La mensajería asíncrona es un amortiguador brutal contra APIs externas inestables. Si la pasarela de pagos, el ERP de un cliente o la API de la AEAT se caen una hora, los mensajes se acumulan en el broker y se procesan cuando vuelven. Sin mensajería, esa caída son errores 500 al usuario y tickets de soporte el lunes.
Patrones de implementación clave
Outbox pattern
El problema típico al empezar con eventos: escribes en tu base de datos local y luego publicas el evento en el broker. ¿Qué pasa si la base confirma pero el broker está caído? Datos inconsistentes y dolor de cabeza.
El outbox pattern resuelve esto guardando el evento en una tabla de la propia base de datos dentro de la misma transacción. Un proceso separado (CDC con Debezium funciona muy bien) lee esa tabla y publica los eventos. Si algo falla, reintenta.
Saga pattern
Cuando una operación de negocio toca varios servicios, el saga pattern coordina los pasos. Cada servicio hace su parte, emite un evento y lanza el siguiente. Si algo falla a mitad, emites eventos de compensación. Lo más cercano a una transacción distribuida sin meterte en 2PC.
Dead letter queues
Los mensajes que no se pueden procesar tras varios intentos van a una dead letter queue. Sin esto, un mensaje veneno te puede bloquear toda una cola y dejar el sistema parado. Con DLQ lo apartas, lo analizas con calma y decides qué hacer.
Escalabilidad y resiliencia
La escalabilidad sale casi de regalo. ¿Una cola acumula mensajes? Más instancias del consumidor. ¿Un servicio tira más que el resto? Lo escalas sin tocar los demás. Cada componente se dimensiona según su carga real.
La resiliencia también mejora mucho. Cuando un consumidor se cae, los mensajes esperan en el broker en lugar de perderse. Cuando se recupera, retoma donde lo dejó. El usuario rara vez se entera, que es justo lo que querías.
Conclusión
Diseñar una arquitectura de eventos con mensajería asíncrona para tu aplicación a medida no es una moda. Es una decisión estratégica que prepara tu sistema para crecer sin que cada nueva funcionalidad cueste el doble que la anterior. RabbitMQ y Kafka te dan la infraestructura; CQRS y event sourcing los patrones para domar la complejidad.
Lo que no haría nunca es meter todos estos patrones desde el día uno por si acaso. Empieza con lo que el negocio necesita hoy, deja la arquitectura preparada para incorporar piezas cuando duela, y mide antes de añadir complejidad. He visto equipos pequeños hundirse intentando montar event sourcing antes de tener producto. No hagas eso.
Si quieres explorar cómo una arquitectura de eventos puede transformar tu aplicación a medida, Contacta con Tangram Consulting.