La arquitectura orientada a eventos (EDA, Event-Driven Architecture) es un estilo de diseño en el que los componentes de un sistema se comunican mediante la producción y el consumo de eventos, en lugar de invocarse directamente unos a otros. Este enfoque favorece el desacoplamiento, la escalabilidad y la capacidad de reaccionar en tiempo real a lo que ocurre en el negocio. En esta lección sentaremos las bases conceptuales que necesitarás para entender el resto del módulo: qué es un evento, en qué se diferencia de un comando y de un mensaje, qué papel juegan los productores y consumidores, y qué topologías existen para conectarlos.

Comprender bien estos fundamentos es esencial porque casi todos los sistemas modernos de gran escala (banca, e-commerce, streaming, IoT) se apoyan en eventos para integrar microservicios sin que se conozcan entre sí.

Contenido

  1. ¿Qué es la arquitectura orientada a eventos?
  2. Evento vs comando vs mensaje
  3. Productores y consumidores
  4. Topología de mediador (mediator)
  5. Topología de broker
  6. Diagrama general de flujo de eventos
  7. Errores comunes y consejos
  8. Ejercicios y soluciones
  9. Conclusión

  1. ¿Qué es la arquitectura orientada a eventos?

Un evento representa algo que ya ha ocurrido en el sistema y que es relevante para el negocio. Ejemplos: "PedidoCreado", "PagoConfirmado", "UsuarioRegistrado". Lo importante es el tiempo verbal: el evento es un hecho consumado e inmutable.

En una arquitectura orientada a eventos:

  • Los componentes emiten eventos cuando cambia su estado.
  • Otros componentes reaccionan a esos eventos sin que el emisor sepa quién los está escuchando.
  • La comunicación es típicamente asíncrona: el emisor no espera respuesta.

Esto contrasta con la arquitectura tradicional basada en llamadas síncronas (REST/RPC), donde el cliente conoce y depende del servidor.

Característica Llamada síncrona (REST/RPC) Arquitectura orientada a eventos
Acoplamiento Fuerte (cliente conoce servidor) Débil (emisor no conoce receptor)
Temporalidad Bloqueante (espera respuesta) No bloqueante (fire-and-forget)
Escalabilidad Limitada por el más lento Alta (consumidores independientes)
Tolerancia a fallos Si el servidor cae, falla la llamada El evento puede procesarse más tarde

  1. Evento vs comando vs mensaje

Estos tres términos se confunden a menudo. Son tipos de mensajes, pero con intenciones diferentes.

Concepto Intención Tiempo verbal Dirección ¿Espera respuesta?
Comando Ordenar que algo ocurra Imperativo: "CrearPedido" 1 emisor → 1 receptor concreto A veces
Evento Notificar que algo ocurrió Pasado: "PedidoCreado" 1 emisor → N receptores desconocidos No
Mensaje Término genérico que engloba a ambos Depende

Veamos un ejemplo en código para fijar la diferencia entre comando y evento:

// COMANDO: una instrucción dirigida a un destinatario concreto.
// Se espera que ALGUIEN lo ejecute. Nombre en imperativo.
public record CrearPedidoCommand(
        String clienteId,
        List<LineaPedido> lineas) {
}

// EVENTO: el hecho de que el pedido YA se ha creado.
// Es inmutable, lleva un identificador y una marca de tiempo.
// Nombre en pasado.
public record PedidoCreadoEvent(
        String pedidoId,
        String clienteId,
        BigDecimal total,
        Instant ocurridoEn) {
}

Explicación detallada del fragmento:

  • record es una clase Java inmutable y concisa (desde Java 16), ideal para representar datos que no cambian, como los eventos.
  • CrearPedidoCommand usa un verbo en imperativo porque expresa una intención de que algo suceda. Normalmente lo procesa un único componente responsable.
  • PedidoCreadoEvent usa el participio "Creado" porque describe un hecho pasado. Incluye ocurridoEn (un Instant, marca temporal UTC) porque todo evento debe poder ordenarse en el tiempo.
  • El evento contiene el total ya calculado: transporta el resultado, no la orden de calcularlo.

Regla práctica: si puedes rechazar la petición, probablemente es un comando. Si solo estás informando de que ocurrió y nadie puede "negarse", es un evento.

  1. Productores y consumidores

En EDA distinguimos dos roles fundamentales:

  • Productor (Producer / Publisher): el componente que detecta un cambio y emite el evento. No sabe (ni le importa) quién lo consumirá.
  • Consumidor (Consumer / Subscriber): el componente que recibe el evento y reacciona (actualiza una base de datos, envía un correo, llama a otro servicio...).
// PRODUCTOR: publica el evento en un canal. No conoce a los consumidores.
@Service
public class ServicioPedidos {

    private final PublicadorEventos publicador; // abstracción del canal

    public ServicioPedidos(PublicadorEventos publicador) {
        this.publicador = publicador;
    }

    public void crearPedido(CrearPedidoCommand cmd) {
        // 1. Lógica de negocio: persistir el pedido
        String pedidoId = UUID.randomUUID().toString();
        // ... guardar en base de datos ...

        // 2. Publicar el evento de lo que ha ocurrido
        var evento = new PedidoCreadoEvent(
                pedidoId, cmd.clienteId(), calcularTotal(cmd), Instant.now());
        publicador.publicar("pedidos.creados", evento);
    }
}

Puntos clave:

  • PublicadorEventos es una abstracción: oculta si por debajo usamos Kafka, RabbitMQ, etc. Esto permite cambiar la tecnología sin tocar la lógica de negocio.
  • Tras guardar el pedido, el servicio publica en el canal lógico "pedidos.creados". No hay ninguna referencia a quién escucha.
// CONSUMIDOR: se suscribe al canal y reacciona al evento.
@Component
public class NotificadorCliente {

    @EventListener("pedidos.creados") // se suscribe al mismo canal
    public void alCrearPedido(PedidoCreadoEvent evento) {
        // Reacción: enviar confirmación al cliente
        enviarEmailConfirmacion(evento.clienteId(), evento.pedidoId());
    }
}
  • El consumidor NotificadorCliente reacciona enviando un correo. Otro consumidor (por ejemplo, ServicioFacturacion) podría escuchar el mismo evento para emitir una factura. Añadir nuevos consumidores no requiere modificar al productor: ahí reside la potencia de EDA.

  1. Topología de mediador (mediator)

Existen dos grandes topologías para organizar el flujo de eventos. La primera es la topología de mediador.

Aquí, un componente central (el mediador u orquestador) recibe un evento inicial, lo descompone en pasos y coordina su ejecución dirigiendo el flujo de trabajo.

  • Útil cuando el proceso tiene varios pasos con orden y lógica condicional (por ejemplo, un alta de seguro: validar datos → tarificar → emitir póliza → cobrar).
  • El mediador conoce el flujo completo, lo que centraliza la lógica de coordinación.
  • Inconveniente: el mediador puede convertirse en un cuello de botella o en un punto único de fallo, y acopla el conocimiento del proceso en un solo lugar.
flowchart LR
    A[Cliente] -->|Evento inicial| M{Mediador / Orquestador}
    M -->|paso 1| S1[Servicio Validación]
    M -->|paso 2| S2[Servicio Tarificación]
    M -->|paso 3| S3[Servicio Emisión]
    S1 -.respuesta.-> M
    S2 -.respuesta.-> M
    S3 -.respuesta.-> M

En el diagrama, el mediador (M) es quien decide el orden y recoge las respuestas de cada servicio. Los servicios no se conocen entre sí; solo hablan con el mediador.

  1. Topología de broker

La segunda es la topología de broker (mediador ausente). No hay coordinador central: los eventos fluyen libremente a través de un broker (canal/cola) y cada servicio reacciona de forma autónoma, pudiendo a su vez emitir nuevos eventos que disparan a otros.

  • Ideal para flujos simples y altamente desacoplados.
  • Máxima escalabilidad y resiliencia: no hay punto central.
  • Inconveniente: el flujo global queda "repartido" y es más difícil de visualizar y depurar (no hay un sitio donde leer todo el proceso).
flowchart LR
    P[Servicio Pedidos] -->|PedidoCreado| B((Broker))
    B --> I[Servicio Inventario]
    B --> F[Servicio Facturación]
    I -->|StockReservado| B
    F -->|FacturaEmitida| B
    B --> E[Servicio Envíos]

Aquí Servicio Inventario reacciona al PedidoCreado y, a su vez, emite StockReservado, que dispara al Servicio Envíos. El flujo emerge de la suma de reacciones individuales, sin coordinador.

Criterio Mediador Broker
Control del flujo Centralizado Distribuido
Acoplamiento Medio (todos conocen al mediador) Mínimo
Visibilidad del proceso Alta (un solo sitio) Baja (repartido)
Resiliencia Punto único de fallo Muy alta
Casos ideales Flujos complejos y condicionales Flujos simples y desacoplados

  1. Diagrama general de flujo de eventos

Combinando los conceptos, así se ve el flujo básico productor → canal → consumidores:

sequenceDiagram
    participant P as Productor
    participant C as Canal de eventos
    participant C1 as Consumidor 1 (Email)
    participant C2 as Consumidor 2 (Facturación)
    P->>C: publicar(PedidoCreadoEvent)
    C-->>C1: entregar evento
    C-->>C2: entregar evento
    Note over C1,C2: Procesan en paralelo e<br/>independientemente

El productor publica una sola vez; el canal distribuye el evento a todos los suscriptores interesados, que trabajan en paralelo y sin conocerse.

Errores Comunes y Consejos

  • Confundir comandos con eventos. Si nombras un evento en imperativo ("EnviarEmail") estás disfrazando un comando. Usa siempre el pasado para eventos: "EmailSolicitado" o "PedidoCreado".
  • Meter lógica de negocio del consumidor en el productor. El productor no debe saber qué hacen los consumidores. Si lo sabe, vuelves a acoplar.
  • Eventos demasiado "gordos" o demasiado "flacos". Un evento debe llevar los datos suficientes para que el consumidor reaccione sin tener que llamar de vuelta al productor (lo que reintroduce acoplamiento), pero sin convertirse en un volcado de toda la base de datos.
  • Olvidar la marca temporal y el identificador. Todo evento debe ser trazable e idempotentemente identificable.
  • Consejo: empieza con topología de broker para flujos simples y reserva el mediador para procesos con muchos pasos condicionales.

Ejercicios

  1. Clasifica los siguientes mensajes como comando o evento y justifica: (a) "ReservarHabitacion", (b) "PagoRechazado", (c) "ActualizarPrecio", (d) "SesionIniciada".
  2. Dibuja (en pseudocódigo o palabras) cómo se vería un proceso de "alta de cliente" con topología de mediador frente a topología de broker. ¿Cuál elegirías y por qué?
  3. Diseña un record de evento en Java para "FacturaEmitida" que incluya los campos mínimos necesarios para que un consumidor de contabilidad pueda reaccionar sin consultar de vuelta al emisor.

Soluciones

  1. (a) Comando (imperativo, dirigido, puede rechazarse). (b) Evento (hecho pasado, notificación). (c) Comando (orden de cambiar algo). (d) Evento (la sesión ya se inició).
  2. Con mediador: un OrquestadorAltaCliente recibe la petición y llama en orden a validación → creación → bienvenida, gestionando los fallos. Con broker: ServicioRegistro emite ClienteRegistrado; ServicioEmail y ServicioCRM reaccionan de forma independiente. Para un alta simple, el broker es preferible por su bajo acoplamiento; si hubiera muchos pasos condicionales (verificación de identidad, scoring), el mediador facilita el control.
  3. Una solución posible:
public record FacturaEmitidaEvent(
        String facturaId,
        String pedidoId,
        String clienteId,
        BigDecimal importeTotal,
        BigDecimal impuestos,
        String divisa,
        Instant emitidaEn) {
}

Incluye importe, impuestos y divisa para que contabilidad asiente el apunte sin consultar de nuevo.

Conclusión

Hemos visto que la arquitectura orientada a eventos sustituye las llamadas directas por la emisión y consumo de hechos del negocio, logrando un fuerte desacoplamiento. Distinguimos comandos (órdenes), eventos (hechos pasados) y mensajes (el término genérico), y entendimos los roles de productor y consumidor. Finalmente comparamos las dos topologías clave: mediador (control centralizado) y broker (máxima autonomía).

En la siguiente lección, "Mensajería Asíncrona: Colas y Brokers", profundizaremos en la infraestructura que transporta estos eventos: las colas frente a los topics, las garantías de entrega y las tecnologías concretas como RabbitMQ, Kafka y SQS.

Curso de Arquitectura de Aplicaciones

Módulo 1: Fundamentos de la Arquitectura de Aplicaciones

Módulo 2: Principios y Tácticas de Diseño

Módulo 3: Estilos y Patrones Arquitectónicos

Módulo 4: Arquitecturas Distribuidas y Microservicios

Módulo 5: Arquitecturas Dirigidas por Eventos y Mensajería

Módulo 6: Diseño Dirigido por el Dominio (DDD)

Módulo 7: Datos y Persistencia

Módulo 8: Arquitectura en la Nube y Despliegue

Módulo 9: Calidad, Seguridad y Observabilidad

Módulo 10: Evolución, Gobernanza y Casos Prácticos

© Copyright 2026. Todos los derechos reservados