El problema
Empezaste con un topic de SNS llamado pedidos y funcionaba. Luego alguien
necesitó solo los pedidos de España, así que apareció pedidos-es. Después
alguien quiso solo los de importe alto, y nació pedidos-grandes. Hoy tienes
veinte topics, una convención de nombres que nadie recuerda y un productor que
publica en cinco sitios distintos.
El acoplamiento no desapareció al usar un topic. Se mudó: ahora vive en el nombre del canal, y cada consumidor nuevo con un criterio nuevo obliga a crear un topic y a tocar el productor para que publique también ahí.
Es el mismo problema que resolvía el fan-out, un nivel más arriba: seguimos pidiendo al productor que sepa quién escucha.
La solución
Un bus, y reglas que miran dentro del evento.
El productor publica siempre en el mismo bus y no declara destinos. Cada consumidor crea una regla con un patrón sobre el JSON del evento:
{
"detail-type": ["PedidoCreado"],
"detail": {
"pais": ["ES"],
"importe": [{ "numeric": [">", 500] }]
}
}
Nadie tuvo que crear un topic pedidos-españa-grandes. El productor no sabe que
esa regla existe, no se entera si mañana desaparece, y añadir un cuarto
consumidor no toca una sola línea de lo que ya funciona.
Esa es la propiedad que hace que EventBridge escale organizativamente: el coste de sumar un equipo que reacciona a tus eventos deja de recaer sobre ti.
El archivo es lo que suele decidir de verdad
Un bus puede archivar los eventos que pasan por él y reproducirlos después. Es lo que SNS estándar no tiene y no va a tener.
Lo que conviene saber antes de contar con ello:
- La retención se configura en días, y por defecto es indefinida.
- Puedes filtrar con un patrón qué se archiva, no hace falta guardarlo todo.
- Un replay solo puede ir al mismo bus de origen, opcionalmente limitado a reglas concretas.
- Reproducir no consume el archivo: puedes repetirlo tantas veces como quieras.
- Los eventos reproducidos llegan con un campo
replay-name, que permite distinguirlos — y que EventBridge usa para no volver a archivarlos.
Cuándo usarlo
- Publican varios equipos en el mismo sitio y no quieres coordinar un registro de topics.
- Los consumidores quieren subconjuntos distintos del mismo flujo, definidos por el contenido y no por el canal.
- Necesitas replay: recuperarte de un bug, o alimentar una funcionalidad nueva con el pasado.
- Quieres reaccionar a eventos de los propios servicios de AWS — que además llegan al bus por defecto sin coste.
Cuándo NO usarlo
Cómo implementarlo
- Crea un bus propio. El bus por defecto recibe además los eventos de todos los servicios de AWS de tu cuenta; mezclar ahí tus eventos de dominio complica patrones y permisos.
- Fija un esquema de eventos:
source,detail-typey undetailcon versión. Los patrones se escriben contra esos campos, así que son contrato. - Una regla por consumidor lógico, no una regla gigante con cinco destinos.
- Cola SQS entre la regla y la función cuando el consumidor deba aguantar picos o caídas, igual que en un fan-out.
- DLQ en cada destino. Si el destino falla, EventBridge reintenta y luego descarta.
- Archivo desde el principio si algún día vas a querer replay: no se puede archivar hacia atrás.
El código
// ── Publicar: el productor no nombra ningun destino ────────────────
await eb.send(new PutEventsCommand({
Entries: [{
EventBusName: 'app',
Source: 'pedidos',
DetailType: 'PedidoCreado',
Detail: JSON.stringify({ v: 1, id, pais: 'ES', importe: 750 }),
}],
}));
// ── Suscribirse: el consumidor declara su patron ───────────────────
new events.Rule(this, 'AntifraudePedidosGrandes', {
eventBus: bus,
eventPattern: {
source: ['pedidos'],
detailType: ['PedidoCreado'],
detail: { importe: [{ numeric: ['>', 500] }] },
},
// Una cola en medio para que el consumidor absorba picos y caidas,
// exactamente por la misma razon que en un fan-out con SNS.
targets: [new targets.SqsQueue(colaAntifraude, {
deadLetterQueue: dlqAntifraude,
})],
});
// El archivo hay que crearlo ANTES: no se archiva hacia atras.
new events.Archive(this, 'ArchivoPedidos', {
sourceEventBus: bus,
retention: cdk.Duration.days(90),
eventPattern: { source: ['pedidos'] },
});
Te va a morder
Coste
| Concepto | Precio aproximado |
|---|---|
| Eventos personalizados | ~1,00 USD / millón |
| Eventos de servicios de AWS al bus por defecto | sin coste |
| Archivo | por GB almacenado |
| Replay | por evento reproducido |
Comparado con SNS —del orden de 0,50 USD por millón de publicaciones, con las entregas a SQS y Lambda gratis— EventBridge sale claramente más caro por evento. Estás pagando el enrutado por contenido, el archivo y el replay. Si no vas a usar ninguno de los tres, estás pagando de más por nada.
Detalle que conviene aprovechar: reaccionar a un cambio de estado de EC2 o a un
Object Created de S3 no se factura en el bus por defecto. Publicar tus
propios eventos de dominio, sí.
Fuentes
Destinos por regla, reglas con comodines, PutEvents e invocaciones por región,
reglas y buses por cuenta, tamaño del patrón y de la política del bus:
Amazon EventBridge quotas.
Retención indefinida por defecto, filtrado del archivo, replay solo al bus de
origen, ausencia de orden, intervalos de un minuto, recomendación de esperar 10
minutos, 10 replays concurrentes, borrado a los 90 días y campo replay-name:
Archiving and replaying events in Amazon EventBridge.
Cuotas de SNS usadas en la comparación:
Amazon SNS endpoints and quotas.