3.12

Ver en inglés

3.12 Arquitectura orientada a eventos y sistemas de mensajería

Visión general y motivación

La arquitectura orientada a eventos (EDA, por sus siglas en inglés) es un estilo en el que los componentes se comunican emitiendo y reaccionando a eventos, en lugar de invocarse directamente entre sí. Un evento es un hecho: algo que ya ha sucedido, como «PedidoCreado» o «PagoCobrado». El productor anuncia el hecho y sigue su camino, y cualquier número de consumidores reacciona a su propio ritmo, sin que el productor sepa quién lo escucha. Esta es una postura muy distinta a las llamadas de solicitud y respuesta del capítulo 2.3, donde quien invoca pide a un servicio concreto que realice una tarea y espera la respuesta.

Para una gran organización, el atractivo reside en el desacoplamiento a escala. Cuando se dispone de decenas de equipos y cientos de servicios, interconectar todo mediante llamadas directas punto a punto genera una red frágil en la que el cambio de un equipo rompe el de otro y nadie logra rastrear por qué. Los eventos permiten a los equipos integrarse a través de un flujo compartido de hechos, en lugar de a través de las entrañas de los otros, y un consumidor nuevo se incorpora simplemente suscribiéndose, sin que el productor tenga que modificar una sola línea de código. Es precisamente esa propiedad, más que el caudal bruto, la que hace que los enfoques orientados a eventos sigan expandiéndose por las empresas que sustituyen integraciones enredadas y por los gobiernos que necesitan articular agencias que cada una administra sus propios sistemas.

El sector público obtiene un segundo beneficio que resulta fácil de infravalorar: un registro ordenado y durable de lo que ha ocurrido constituye un activo de auditoría y transparencia. Cuando un ciudadano pregunta por qué una decisión de prestaciones salió como salió, un registro inmutable de los eventos que la originaron responde de forma directa. Pero el diseño orientado a eventos no es gratuito y no siempre es la respuesta correcta: los flujos asíncronos son más difíciles de rastrear, de razonar y de aplicar en exceso. Este capítulo toma una postura clara sobre cuándo el desacoplamiento y la escala justifican la complejidad añadida y cuándo una llamada síncrona sencilla habría servido con creces. Se apoya en las realidades de los sistemas distribuidos del capítulo 3.3, así que léalo primero si aún no lo ha hecho.

Principios fundamentales

  • Los eventos son hechos, no instrucciones. Un evento dice qué ha sucedido; un comando pide que algo suceda. Mántenlos diferenciados y nombra los eventos en pasado.
  • El desacoplamiento es el objetivo. Los productores no deben saber ni importarse quién consume sus eventos. Si lo saben, tienen un acoplamiento disfrazado de mensajería.
  • Diseñe para entrega al menos una vez. La entrega exactamente una vez es un mito. Haga que cada consumidor sea idempotente para que las duplicaciones resulten inofensivas.
  • El orden es una garantía que se paga. Se obtiene orden dentro de una partición, no a lo largo de un tema. Elija las claves de partición con deliberación.
  • El esquema es el contrato. La forma de un evento es una interfaz pública; hágalo evolucionar con el mismo cuidado que se tendría con una API publicada.
  • Lo asíncrono no implica inobservable. Si no puede seguir un mensaje de principio a fin, no puede operar el sistema.
  • La complejidad debe ganarse. El event sourcing, el CQRS y las sagas son potentes y costosos; recójalos cuando el problema lo exija, no por defecto.

Recomendaciones

Distinga entre eventos, comandos y mensajes antes de escribir una línea de código

Estas tres palabras se usan indistintamente, y la confusión produce errores de diseño reales. Un comando es una solicitud de acción («CobrarPago»), dirigida a un manejador concreto, y puede ser rechazado. Un evento es una notificación de que algo ya ha ocurrido («PagoCobrado»); se difunde a quien le interese y no puede rechazarse, porque el hecho ya es cierto. Un mensaje es el sobre neutro que transporta, en la red, tanto comandos como eventos. La distinción define el acoplamiento: los comandos enlazan al remitente con un receptor y un resultado concretos, mientras que los eventos renuncian al control sobre lo que ocurra a continuación. Nombra los eventos en pasado, y cuando te sorprendas publicando un «evento» que en realidad significa «ve y haz esta tarea concreta», habrás escrito un comando disfrazado.

Elija colas, registros y publicación/suscripción a conciencia

No toda la mensajería tiene la misma forma, y elegir la equivocada es un error temprano muy frecuente. Una cola de mensajes entrega cada mensaje a un solo consumidor y, por lo general, lo elimina una vez procesado; encaja en la distribución de trabajo: muchos trabajadores que extraen tareas, cada una completada una sola vez. Un registro de eventos durable (un flujo) conserva los eventos en orden y permite que múltiples consumidores independientes lean a su propio ritmo, reproduciendo la historia desde cualquier punto; encaja en la distribución de eventos y en la auditoría. La publicación/suscripción tiene a los productores publicando en un tema y a múltiples suscriptores recibiendo cada uno su propia copia. La regla práctica es simple: si el mensaje es una tarea que un solo trabajador debe completar, use una cola; si es un hecho del que muchas partes pueden interesarse ahora o en el futuro, use un registro durable, que además ofrece la reproducción para la recuperación y la incorporación de nuevos consumidores. Consulte el capítulo 3.4 para ver cómo estas elecciones interactúan con su estrategia de almacenamiento de datos.

Prefiera la coreografía para la autonomía, la orquestación para el control

Cuando un proceso de negocio abarca varios servicios, se coordina de dos maneras. En la coreografía, cada servicio reacciona a los eventos y emite los propios, sin un cerebro central: es máximamente desacoplada y favorece la autonomía del equipo, pero el proceso global existe solo como un comportamiento emergente que ningún lugar describe de forma unificada. En la orquestación, un coordinador central dirige los pasos y conoce el flujo completo: resulta más fácil de monitorizar y modificar, al precio de introducir un componente del que dependen todos los pasos. Un buen punto de partida es la coreografía para reacciones poco relacionadas («cuando un pedido se expide, el servicio de fidelidad otorga puntos») y la orquestación para una transacción bien definida con una condición de éxito clara y la necesidad de informar el estado. No deje que un proceso importante exista solo como conocimiento tribal disperso en diez manejadores de eventos.

Acuda al event sourcing y al CQRS solo cuando se ganen su lugar

El event sourcing almacena el estado como una secuencia de solo-apéndice de eventos en lugar de una instantánea actual que se sobrescribe, y se reconstruye el estado presente reproduciendo los eventos. Las ventajas son una trazabilidad de auditoría perfecta, la capacidad de reconstruir cualquier estado pasado y las consultas temporales; el coste es que hay que versionar los esquemas de eventos para siempre, gestionar la reproducción y las instantáneas, y llevar un modelo mental que la mayoría de los desarrolladores nunca ha usado. El CQRS (segregación de responsabilidades de comandos y consultas) separa el modelo de escritura de uno o varios modelos de lectura para que ambas dimensiones escalen y evolucionen de forma independiente; empareja bien con el event sourcing pero no lo requiere. Ambos brillan en dominios con necesidades genuinas de auditoría, cumplimiento o consultas complejas, por lo que la banca regulada y el sector público los encuentran dignos del esfuerzo. Para un servicio simple de crear-leer-actualizar-eliminar son una complejidad accidental que lamentarán; aplíquelos a la porción de su dominio que realmente los necesita, no al sistema entero por reflejo.

Gestione las transacciones distribuidas con sagas, no con compromiso de dos fases

Por lo general, no se puede envolver una transacción atómica alrededor de varios servicios y bases de datos. El compromiso de dos fases distribuido mantiene bloqueos a través de la red, reduce la disponibilidad y escala mal, por lo que rara vez encaja en un sistema orientado a eventos. El patrón de saga lo reemplaza: se modela la transacción como una secuencia de transacciones locales, cada una emitiendo un evento que dispara la siguiente, y se dota a cada paso de una acción compensatoria que la deshace si un paso posterior falla. Si «reservar inventario» tiene éxito pero «cobrar tarjeta» falla, la compensación libera la reserva. Las sagas pueden ser coreografiadas u orquestadas, y la orquestación suele ganar en todo lo que necesite monitorizarse. Dado que las sagas abrazan la consistencia eventual, el sistema transita por estados intermedios («reservado pero no pagado») antes de converger, de modo que hay que diseñar la experiencia de usuario y la trazabilidad de auditoría para mostrar de forma honesta los estados «en curso» y «compensado». El capítulo 3.3 aborda este mismo terreno desde la perspectiva de los sistemas distribuidos.

Diseñe para entrega al menos una vez y haga idempotentes los consumidores

Los sistemas de mensajería no pueden entregar exactamente una vez con garantía absoluta ante fallos, porque el acuse de recibo que dice «ya lo procesé» puede perderse, obligando a una reentrega. Lo que sí se puede lograr es la entrega al menos una vez con procesamiento idempotente, lo cual produce efectos exactamente una vez. La idempotencia significa que procesar dos veces el mismo evento produce el mismo resultado que procesarlo una; se consigue con una clave de idempotencia en cada evento y un registro de lo que ya se ha gestionado, de modo que una duplicación se reconoce y se descarta. La entrega como mucho una vez (enviar y olvidarse, sin reentrega) es más simple pero pierde mensajes en silencio, así que resérvela para datos que se pueda permitir perder. Trate con recelo la etiqueta de «exactamente una vez» que algunos proveedores anuncian: suele significar exactamente una vez dentro de los límites de un solo sistema y bajo condiciones específicas, no la garantía de extremo a extremo que la frase sugiere.

Controle el orden mediante particiones y conozca sus grupos de consumidores

El orden no es global ni gratuito; es local y tiene un precio. Un flujo se divide en particiones, y se obtiene orden dentro de una partición, no a lo largo de todo el tema. Los eventos se enrutan a una partición por medio de una clave de partición, por lo que elegir esa clave es lo que determina qué se mantiene ordenado: si se particiona por identificador de cliente, los eventos de un mismo cliente se procesan en orden relativo entre sí, mientras que clientes distintos se procesan en paralelo. Los grupos de consumidores permiten a un conjunto de trabajadores compartir las particiones de un tema, con cada partición gestionada por un trabajador, que es la forma de escalar el caudal preservando el orden por partición; aquí es donde la escalabilidad se encuentra con la corrección, conectando con el capítulo 3.5. Elija una clave de partición que refleje la necesidad real de orden y distribuya la carga de forma uniforme, porque una clave que canaliza la mayor parte del tráfico hacia una sola partición crea un punto caluroso que ninguna cantidad de trabajadores puede aliviar.

Trate los esquemas como contratos con un registro y reglas de evolución

La estructura de un evento es una interfaz publicada que consumen equipos con los que quizá nunca se cruce, por lo que cambiarla con descuido los rompe a distancia. Coloque los esquemas de eventos en un registro de esquemas, un catálogo compartido que almacena cada esquema y aplica reglas de compatibilidad cuando un productor intenta modificarlo. Adapte una política explícita: los cambios compatibles con versiones anteriores (añadir un campo opcional) están permitidos; los que rompen compatibilidad (eliminar un campo, cambiar un tipo, renombrar) requieren una nueva versión del esquema y un plan de migración. Esto permite que los productores evolucionen sin una puesta en producción sincronizada en cada consumidor, que es toda la razón por la que se eligieron los eventos. La misma disciplina de versionado de interfaces del capítulo 2.3 se aplica aquí, porque un esquema de evento es una API con otro nombre.

Garantice la entrega con la bandeja de salida transaccional y maneje los fallos de forma explícita

Un fallo clásico: el servicio escribe en su base de datos y luego publica un evento, y se cae entre ambas operaciones, de modo que la base de datos cambió pero el evento nunca salió. La bandeja de salida transaccional lo corrige escribiendo el evento en una tabla de salida dentro de la misma transacción de base de datos que el cambio de estado, de modo que ambas se confirman o fallan juntas; un relay separado lee la bandeja y publica en el broker, a menudo utilizando la captura de datos de cambio para seguir el registro de la base de datos. Para los fallos de consumo, una cola de mensajes no procesables retiene los mensajes que fallan repetidamente para que un mensaje envenenado (uno que nunca tendrá éxito, quizá porque está mal formado) no bloquee la cola por detrás indefinidamente. Añada contrapresión para que un productor rápido no abruma a un consumidor lento: acote las colas y ralentice o descarte carga cuando se llenen, en lugar de agotar la memoria. Estas cuatro mecanismos separan un demostrador de un sistema que puede sostenerse a las tres de la mañana.

Haga observables los flujos asíncronos de extremo a extremo

El coste más difícil de pasar a lo orientado a eventos es que una única acción de negocio se dispersa ahora entre productores, brokers y consumidores sin una pila de llamadas que los ligue. Propague un identificador de correlación a través de cada evento para poder seguir un flujo lógico en cada salto, la misma disciplina que el capítulo 3.3 prescribe para las llamadas síncronas. Vigile el retraso del consumidor (cuán por detrás del tiempo real está leyendo cada consumidor) como una métrica de primera clase, porque un aumento del retraso es la primera señal de que algo va mal, y también monitorice la profundidad de la cola de mensajes no procesables, la latencia de procesamiento y las tasas de reentrega. Sin esto, un evento que fracasa silenciosamente en consumirse se convierte en un fallo invisible que surge días después como datos faltantes.

Compromisos: ventajas y desventajas

EnfoqueVentajasDesventajas / coste
Solicitud/respuesta síncronaSimple de razonar, resultado inmediato, rastreo fácilAcoplamiento temporal fuerte, fallos en cascada, escalabilidad limitada
Orientado a eventos (publicación/suscripción sobre un registro)Desacoplamiento, escalado independiente, reproducción, trazabilidad de auditoríaConsistencia eventual, rastreo más difícil, más componentes en juego
Cola de mensajes (distribución de trabajo)Niveación de carga, almacenamiento en búfer, tolerante a la contrapresiónUn solo consumidor por mensaje, menos apto para la difusión
Event sourcing + CQRSHistorial completo, consultas temporales, lectura/escritura escalan de forma independienteVersionado de esquemas perpetuo, complejidad de reproducción, curva de aprendizaje pronunciada
Saga (frente al compromiso de dos fases)Escalable, disponible, sin bloqueos distribuidosConsistencia eventual, lógica de compensación, más difícil de razonar

La tensión central está entre el desacoplamiento y la comprensibilidad. Cada evento que se añade afloja el acoplamiento entre productor y consumidor, comprando autonomía de equipo y escalado independiente, y al mismo tiempo borra una línea de la historia que una llamada síncrona habría contado con claridad: el flujo se vuelve emergente, vive en las interacciones y no en ningún archivo único. La resolución es ser selectivo: usar eventos donde el desacoplamiento paga de verdad, como la integración entre fronteras de equipo, la difusión a muchos consumidores, el amortiguamiento de picos de carga y la auditoría. Mantener las llamadas síncronas donde se necesita una respuesta inmediata y un modelo mental simple, como leer datos para renderizar una página. El fallo a evitar es convertir cada llamada de función interna en un evento y llamarlo arquitectura, el mismo juicio arquitectónico que el capítulo 3.2 exige al adoptar cada patrón.

Preguntas para debatir con el equipo

  1. ¿Para esta interacción concreta, realmente necesitamos un evento o una llamada síncrona sería más clara y segura? Saltarse esta pregunta es como un sistema acumula complejidad accidental. La prueba honesta es si el productor necesita el resultado ahora mismo (una llamada) o si está anunciando un hecho del que otros pueden reaccionar a su propio ritmo (un evento). Lleve la interacción concreta, no una preferencia general, y pregunte qué desacoplamiento se gana y qué claridad de rastreo se renuncia. Si quien invoca bloquea esperando a que el «evento» se procese, ha construido una llamada síncrona lenta y difícil de depurar, y ha pagado de más por el privilegio. El valor por defecto para interacciones internas del mismo equipo donde se necesita la respuesta ahora debe ser una llamada directa; reserve los eventos para donde el desacoplamiento justifique su coste.

  2. ¿Qué pasa cuando un consumidor recibe el mismo evento dos veces, y realmente lo hemos probado? La entrega al menos una vez garantiza que las duplicaciones ocurrirán, por lo que cada consumidor debe ser idempotente, pero la idempotencia es fácil de afirmar y fácil de ejecutar mal. Recorra un consumidor real y trace exactamente cómo una segunda entrega se reconoce y neutraliza, ya sea por una clave de idempotencia, un registro de eventos procesados o una operación naturalmente idempotente. Lleve los resultados de una prueba real en la que se reenvía un lote y se confirma que no hay cobros duplicados, registros repetidos ni notificaciones dobles. Preste especial atención a los efectos secundarios que salen de la base de datos, como correos electrónicos, pagos y llamadas a terceros, porque allí es donde los errores de no idempotencia afectan directamente a los clientes. Si el equipo no puede señalar una prueba que demuestre la seguridad ante duplicaciones, asúmase no seguros.

  3. Cuando un flujo de eventos se rompe en producción, ¿cuánto tardamos en notarlo y podemos rastrear un mensaje de extremo a extremo? Los fallos asíncronos son silenciosos, así que un consumidor que deja de procesar en silencio puede pasar desapercibido hasta que los datos faltantes se convierten en una queja de cliente o un vacío de auditoría. Pregunte cuál es la primera señal, y si el retraso del consumidor y la profundidad de la cola de mensajes no procesables se tratan como métricas de alerta y no como paneles que nadie mira. Lleve un incidente real o un ejercicio tipo simulacro y cronometre cuánto tarda en seguir un solo identificador de correlación a través del productor, el broker y cada consumidor. Si la respuesta es «buscamos en varios servicios y adivinamos», la observabilidad no está preparada para la complejidad asumida. En sectores regulados, poder reconstruir exactamente cómo se movió un mensaje suele ser un requisito de cumplimiento, no una cortesía.

  4. ¿Cómo evolucionaremos un esquema de evento que muchos equipos ya consumen sin romper ninguno de ellos? La forma de un evento es un contrato público, y cuando decenas de consumidores dependen de él, un cambio aparentemente inocente puede romper sistemas de los que nunca se ha oído hablar, a distancia, sin un compilador que avise. La tensión es real: los productores quieren avanzar rápido y limpiar sus eventos, mientras que cada consumidor quiere que la forma quede congelada para siempre; por eso hay que acordar de antemano qué cambios son seguros (añadir un campo opcional) y cuáles exigen una nueva versión y una ventana de migración (eliminar un campo, cambiar un tipo, renombrar). Lleve la lista real de consumidores por tema, si un registro de esquemas aplica reglas de compatibilidad hoy o si las formas cambian por acuerdo informal, y cuánto tiempo pueden coexistir dos versiones durante una migración. En una gran empresa o en un acuerdo de intercambio de datos entre agencias gubernamentales, un esquema roto en silencio puede corromper registros en sistemas que no se poseen y manifestarse después como un fallo de auditoría, así que el control de compatibilidad es gobernanza, no cortesía.

  5. Para nuestra transacción multieservicio más importante, ¿qué deshace cada acción compensatoria y qué estados intermedios verán los usuarios y los auditores? Las sagas cambian la ilusión reconfortante de una transacción atómica única por una secuencia de pasos locales que cada uno puede fallar, por lo que el sistema transita de verdad por estados como «reservado pero no pagado» y «cobrado pero no expidió» antes de converger, y pretender lo contrario es como se despliega una saga que pierde dinero o deja registros huérfanos. Recorra el proceso real de extremo a extremo, nombre la compensación de cada paso (qué libera la reserva, qué reembolsa la tarjeta), y decida si una saga orquestada que se puede monitorizar supera a una coreografía emergente que ningún lugar describe de forma unificada. Lleve los casos de fallo que se han probado de verdad, no el camino feliz, y confirme que la experiencia de usuario y la trazabilidad de auditoría muestran los estados «en curso» y «compensado» con honestidad, en lugar de ocultarlos. En sistemas de finanzas, prestaciones o impuestos, un regulador preguntará qué aspecto tenía el registro en cada momento intermedio y quién era responsable de la compensación, por lo que los estados de la saga son en sí mismos un artefacto de cumplimiento.

  6. ¿Quién gestiona el broker o el registro de eventos, y se ha contado el coste real de operarlo frente a una alternativa gestionada? La columna vertebral de mensajería no es infraestructura gratuita que aparece al dibujarla en un diagrama: alguien la parchea, escala sus particiones, ajusta la retención, responde cuando suena la alarma a las tres de la mañana, y es el dueño de su capacidad y sus modos de fallo. Decida de forma deliberada entre autoalojar un broker de código abierto y contratar un servicio gestionado, sopesando el control y la residencia de datos frente a la carga operativa y el coste de la licencia, y sea honesto sobre si el equipo tiene la profundidad necesaria para gestionar bien un registro distribuido. Lleve el coste total de propiedad: carga de guardia, las especialidades requeridas, la factura de retención y almacenamiento, y qué hace una caída del broker a cada flujo dependiente. Para una empresa, la respuesta define el mandato de un equipo de plataforma; para un organismo público, las reglas de contratación, los requisitos de soberanía de datos y la necesidad de evitar el vendor lock-in pueden prevalecer sobre la opción más barata, así que haga visibles esas restricciones antes de comprometerse con una tecnología que se llevará a diez años.

Perspectiva sectorial

Startup. El recurso más escaso es la atención de ingeniería, así que permanezca en lo síncrono hasta que la difusión realmente duela. Cuando tres cosas necesiten reaccionar a una acción, publique un único evento (como «PedidoCreado») en una cola o registro gestionado en lugar de montar un clúster propio de broker, y mantenga el pago y lo que necesite una respuesta inmediata como una llamada directa. No adopte event sourcing, CQRS ni sagas para parecer sofisticado; esa complejidad desbordará a un equipo diminuto y frenará la misma iteración en la que compite.

Pequeña empresa. No hay especialista en mensajería ni ganas de gestionar Kafka, así que trate la integración asíncrona como algo que se compra, no que se opera. Aproveche los eventos que sus herramientas ya emiten (webhooks, las colas integradas en el proveedor de nube o en las plataformas SaaS) y deje que un servicio gestionado asuma la entrega, la retención y la plomería de la idempotencia. Encare la elección como comprar-frente-a-construir con honestidad: un puñado de manejadores de webhooks fiables supera a un broker artesanal que no se puede cubrir ni depurar a las tres de la mañana.

Empresa grande. El problema es el coste de integración entre muchos equipos, así que el retorno es una plataforma compartida y gobernada: un registro de eventos durable, un registro de esquemas con una política de compatibilidad forzada, una propiedad clara de los temas y patrones estándar de idempotencia y bandeja de salida para que cada equipo no tenga que reinventarlos. Es el escenario en el que reemplazar un bus de servicios empresarial frágil o una red de enlaces punto a punto se convierte en un ahorro real, y en el que las sagas orquestadas con estado visible permiten al personal de operaciones gestionar procesos de varios pasos. Presupueste explícitamente la inversión en observabilidad y gobernanza de esquemas, porque a esta escala un fallo de consumidor silencioso se convierte en datos faltantes en decenas de sistemas.

Sector público. Un registro de eventos durable y ordenado es un activo de auditoría y transparencia: responde a «¿por qué esta decisión salió así?» con una secuencia inmutable de hechos, así que se abra al event sourcing donde la rendición de cuentas lo exija. El intercambio de datos entre agencias necesita entrega al menos una vez con deduplicación sobre un identificador de evento estable, para que un registro reentregado nunca genere un caso duplicado, y la contratación debe sopesar la soberanía de datos, el conocimiento de las limitaciones del broker y la portabilidad frente al vendor lock-in. Publique, en su caso, cómo funciona el flujo y cómo un ciudadano puede impugnar un resultado automatizado, y mantenga el registro de eventos como el registro defensible que los órganos de supervisión pidan inspeccionar.

Ejemplos

Startup. Una pequeña tienda de comercio electrónico empieza con un flujo síncrono: el pago invoca el servicio de cobro y espera. Al crecer, quiere que los correos de confirmación de pedido, la actualización de inventario y un programa de fidelidad reaccionen a las compras, y cablear cada uno como otra llamada síncrona dentro del pago lo vuelve lento y frágil. El equipo publica un único evento «PedidoCreado» en un registro durable y deja que tres consumidores independientes reaccionen, de modo que el pago vuelve a ser rápido y añadir una cuarta reacción más adelante no requiere cambiarlo. Mantienen la captura de pago síncrona, porque necesitan la respuesta sí o no antes de confirmar el pedido, que es exactamente la línea trazada correcta a su tamaño.

Empresa grande. Un asegurador global se ahoga en integraciones punto a punto y un bus de servicios empresarial (ESB) envejecido, un hub central por el que cada sistema enrutaba y que se ha convertido en un cuello de botella y un único punto de fallo. Migran a un registro de eventos durable donde cada dominio publica sus hechos (póliza emitida, reclamación presentada, pago realizado) y los equipos consumidores se suscriben a lo que necesitan. Una saga de reclamaciones, orquestada para que el personal de operaciones vea el estado de cada reclamación, coordina la liquidación de varios pasos con compensaciones para los pasos que fallan. Un registro de esquemas permite que el equipo de pólizas haga evolucionar sus eventos sin una puesta en producción sincronizada en cuarenta sistemas consumidores, precisamente la fragilidad que imponía el viejo ESB.

Sector público. Una agencia tributaria nacional debe dar a ciudadanos y auditores una respuesta defendible a «¿por qué mi liquidación salió así?». Modela el dominio de la liquidación con event sourcing, de modo que cada cambio es un evento inmutable en un registro ordenado y la liquidación actual es la reproducción de esos eventos; cuando un ciudadano impugna una cifra, un casuístico reconstruye el estado exacto en cualquier fecha pasada y muestra la secuencia de hechos que la produjo. El intercambio de datos interagencial se ejecuta sobre temas durables con entrega al menos una vez, y cada agencia, como consumidora, deduplica sobre un identificador de evento para que un registro reentregado nunca genere un caso duplicado. El registro de eventos sirve dobladamente como la trazabilidad de auditoría que los organismos de supervisión exigen, convirtiendo una obligación de cumplimiento en un subproducto del diseño.

Casos de negocio: motivaciones, retorno y coste total de propiedad

El retorno de la arquitectura orientada a eventos lo domina una cosa: el coste de la integración a lo largo del tiempo. La integración punto a punto hace que ese coste crezca con el número de conexiones, que crece más rápido que el número de sistemas, de modo que la integración se convierte en el impuesto que devora la capacidad de entrega. Los eventos aplanan esto, porque los equipos se integran a través de un flujo compartido de hechos, un consumidor nuevo se incorpora suscribiéndose y los productores evolucionan detrás de un esquema versionado, por lo que el coste marginal de la siguiente integración cae en picado. Esa es la historia central de retorno que hay que contar a la dirección: no el rendimiento bruto, sino la reducción compuesta del coste del cambio a lo largo de muchos equipos.

Nomine el coste total de propiedad con honestidad para ser creíble. Se asume la infraestructura del broker que hay que gestionar, la gobernanza de esquemas que hay que mantener y una curva de aprendizaje operativo más pronunciada, porque los sistemas asíncronos son genuinamente más difíciles de depurar; presupueste la inversión en observabilidad desde el principio. Sopesese estos costos frente al coste de no adoptar eventos donde encajan: una capa de integración fosilizada donde cada cambio es un proyecto de coordinación multiequipo, un ESB heredado que se ha convertido en un cuello de botella que nadie se atreve a tocar y la incapacidad de añadir capacidades sin alterar las antiguas. Para la empresa que reemplaza cableado punto a punto frágil y para el sector público que construye trazas de auditoría durables, el retorno es más fuerte donde las necesidades de auditoría y desacoplamiento son reales. Donde esas necesidades no existen, la respuesta honesta es que un diseño síncrono más simple tiene un coste total de propiedad menor, y hay que decirlo.

Antipatrones y trampas

  • El monolito distribuido disfrazado. Servicios que deben desplegarse todos juntos y dependen de los eventos internos de los otros. Se ha añadido un broker pero se ha mantenido el acoplamiento, así que se tienen las desventajas de ambos estilos.
  • Eventos como comandos. Publicar «eventos» que en realidad significan «haz esta tarea concreta por mí», recreando un acoplamiento fuerte con latencia extra y peor trazabilidad.
  • Suponer entrega exactamente una vez. Consumidores que se rompen, cobran dos veces o duplican registros cuando el broker inevitablemente reentrega un mensaje.
  • Event sourcing en todo. Aplicar event sourcing y CQRS a dominios simples de crear-leer-actualizar-eliminar que nunca necesitaron historial, comprando una complejidad pronunciada sin beneficio alguno.
  • Sin gobernanza de esquemas. Productores que cambian las formas de los eventos a su antojo, rompiendo a los consumidores aguas abajo a distancia sin ningún control de compatibilidad.
  • Ignorar la bandeja de salida. Escribir en la base de datos y publicar un evento como dos pasos separados, de modo que una caída entre ambos pierde eventos en silencio o emite fantasmas.
  • Sin manejo de cola de mensajes no procesables. Un solo mensaje envenenado bloquea una partición, o los mensajes fallidos desaparecen sin una cola que los atrape e inspeccione.
  • Flujos invisibles. Procesamiento asíncrono sin identificadores de correlación, sin alertas de retraso del consumidor y sin trazado, de modo que los fallos permanecen silenciosos hasta que se convierten en datos faltantes.

Modelo de madurez

  • Nivel 1, Iniciar: La integración es ad hoc, con llamadas punto a punto, o existe un broker pero se usa como solicitud/respuesta síncrona. Las duplicaciones rompen los consumidores, no hay disciplina de esquemas ni trazado entre saltos, y los mensajes fallidos desaparecen en silencio.
  • Nivel 2, Desarrollar: Un broker o registro se usa en flujos reales y algunos equipos tienen prácticas básicas: los consumidores van haciéndose idempotentes y las colas de mensajes no procesables atrapan algunos fallos. Pero el enfoque es inconsistente entre equipos, eventos y comandos siguen entrelazados, los esquemas cambian por acuerdo informal y la observabilidad es escasa.
  • Nivel 3, Estándarizar: Se distingue deliberadamente entre eventos, comandos y mensajes en toda la organización. Los consumidores son idempotentes por norma, los esquemas viven en un registro con una política de compatibilidad documentada y forzada, y la bandeja de salida transaccional garantiza la entrega. Las sagas con compensaciones gestionan las transacciones multieservicio, los identificadores de correlación se propagan en cada salto, y estos patrones están escritos y se aplican de forma consistente en lugar de dejarse al criterio de cada equipo.
  • Nivel 4, Gestionar: La plataforma de eventos se mide y controla con datos frente a líneas base. El retraso del consumidor, la profundidad de la cola de mensajes no procesables, las tasas de reentrega y la latencia de procesamiento se rastrean como métricas de alerta con umbrales acordados, no como paneles que nadie mira; la compatibilidad de esquemas se verifica automáticamente antes de que un productor pueda desplegar un cambio; la reproducción, el manejo de fallos y la idempotencia se prueban en un calendario fijo y no se dan por supuestos. Si una interacción concreta debe ser un evento o una llamada síncrona se decide con evidencia, y la capacidad, el coste de retención y la fiabilidad de cada broker se revisan frente a objetivos.
  • Nivel 5, Orquestar: Se eligen los estilos orientado a eventos y síncrono por interacción como un segundo natura, y el event sourcing y el CQRS se aplican con precisión donde las necesidades de auditoría y consulta los justifican y en ningún otro sitio. Los flujos asíncronos son tan observables como los síncronos, la plataforma mejora de forma continua conforme cambian las necesidades (retirando temas en desuso, haciendo evolucionar la gobernanza de esquemas, reequilibrando particiones) y la mensajería está integrada con la estrategia arquitectónica y de auditoría más amplia, de modo que la organización adapta su diseño de eventos a medida que cambian el negocio y sus obligaciones.

Ideas para la reflexión

  1. ¿Cuáles de los «eventos» actuales son en realidad comandos, y qué acoplamiento se eliminaría modelándolos con honestidad?
  2. Si mañana se reprodujera un día completo de eventos a través de los consumidores, ¿qué se rompería, y qué revela eso sobre la idempotencia y la seguridad ante la reproducción?
  3. ¿Qué partes del dominio necesitan de verdad la traza de auditoría del event sourcing y cuáles son un estado simple que solo se complicaría al aplicarlo?
  4. ¿Cómo se migraría de un bus de servicios empresarial heredado o de una red de integraciones punto a punto sin un corte en bloque arriesgado?
  5. Para el proceso multieservicio más importante, ¿es una saga orquestada de verdad con compensaciones, o una coreografía emergente que ningún lugar describe de forma unificada?

Puntos clave

  • La arquitectura orientada a eventos compra desacoplamiento, escalado independiente, reproducción y trazas de auditoría, y cuesta comprensibilidad y complejidad operativa; hay que elegirla por interacción, donde el beneficio sea real.
  • Mantener diferenciados los eventos (hechos ocurridos), los comandos (solicitudes de acción) y los mensajes (el sobre), porque la confusión produce errores de acoplamiento reales.
  • Diseñar para entrega al menos una vez y hacer idempotente a cada consumidor; la entrega exactamente una vez es un mito, y los efectos exactamente una vez son un logro de ingeniería.
  • El orden es por partición, los esquemas son contratos que pertenecen a un registro, y la bandeja de salida, la cola de mensajes no procesables y la contrapresión son la plomería que hace que la mensajería sea apta para producción.
  • Usar sagas con compensaciones en lugar del compromiso de dos fases, y acudir al event sourcing y al CQRS solo donde las necesidades de auditoría y consulta justifiquen su coste pronunciado.
  • Los flujos asíncronos son silenciosos cuando fallan, por lo que los identificadores de correlación, la monitorización del retraso del consumidor y el trazado de extremo a extremo marcan la diferencia entre un sistema operable y uno invisible.

Referencias y lecturas complementarias

  • Martin Kleppmann, Designing Data-Intensive Applications
  • Gregor Hohpe y Bobby Woolf, Enterprise Integration Patterns
  • Chris Richardson, Microservices Patterns (sagas, bandeja de salida transaccional, CQRS)
  • Sam Newman, Building Microservices
  • Ben Stopford, Designing Event-Driven Systems
  • Adam Bellemare, Building Event-Driven Microservices
  • Vaughn Vernon, Implementing Domain-Driven Design (event sourcing y CQRS)
  • Martin Fowler, «Event Sourcing» y «CQRS» (artículos en martinfowler.com)
  • Hector Garcia-Molina y Kenneth Salem, «Sagas» (1987)