Arquitetura Event-Driven sem virar um monolito distribuído
Quando eventos ajudam a desacoplar times e quando eles só escondem acoplamento atrás de uma fila. Um guia prático de trade-offs.
Arquiteturas orientadas a eventos viraram quase um sinônimo de "sistema moderno". Mas adotar eventos sem entender os trade-offs é a forma mais rápida de transformar um monólito organizado em um monolito distribuído — todas as dependências de antes, agora com latência de rede e debugging por correlação.
O que eventos realmente resolvem
Eventos não são sobre tecnologia (Kafka, SQS, RabbitMQ). São sobre inversão de dependência no tempo. O produtor não sabe — e não precisa saber — quem consome.
Isso desacopla de verdade quando:
- Times diferentes evoluem produtores e consumidores em ritmos diferentes.
- O mesmo fato de negócio dispara várias reações independentes.
- Você precisa absorver picos de carga com um buffer natural.
Quando é acoplamento disfarçado
O sinal de alerta aparece quando o produtor emite um evento e espera uma resposta específica de um consumidor específico para seguir. Isso não é um evento — é uma chamada RPC com passos extras.
Se você precisa saber quem vai consumir e o que vai acontecer depois, você provavelmente quer uma chamada síncrona, não um evento.
Um teste prático
Antes de transformar uma interação em evento, pergunte:
- O produtor fica correto mesmo que ninguém consuma o evento?
- A ordem de processamento entre consumidores é irrelevante para a correção?
- Você consegue conviver com consistência eventual nesse fluxo?
Se a resposta para as três for "sim", eventos provavelmente ajudam. Se alguma for "não", o custo operacional raramente compensa.
Exemplo: notificação vs. cobrança
// ✅ Bom uso de evento: reações independentes a um fato consumado
await orders.markAsPaid(orderId);
await bus.publish("order.paid", { orderId, amount });
// e-mail, fiscal e analytics reagem sem o checkout saber delesAgora compare com:
// ⚠️ Acoplamento disfarçado: o checkout depende do resultado
await bus.publish("charge.requested", { orderId });
// ...e fica "esperando" um charge.completed para liberar o pedidoNo segundo caso, a corretude do checkout depende do consumidor. Uma chamada síncrona ao serviço de pagamento — com um circuit breaker — seria mais simples de operar e de depurar.
Conclusão
Eventos são uma ferramenta de desacoplamento, não um selo de modernidade. Use-os onde a independência entre produtores e consumidores é real. Onde há dependência de resultado, prefira chamadas explícitas. A arquitetura mais fácil de operar quase sempre é a mais honesta sobre suas dependências.