Arquitetura Orientada a Eventos: Quando usar eventos — e quando evitá-los
Arquitetura orientada a eventos virou praticamente padrão em sistemas modernos.
Kafka, RabbitMQ, filas, listeners, webhooks, microsserviços — tudo parece empurrar times para um modelo cada vez mais distribuído e assíncrono.
Mas existe um problema:
Muitos sistemas começam a usar eventos sem entender exatamente o que um evento representa.
O resultado normalmente é o mesmo:
- lógica espalhada
- fluxo invisível
- dificuldade absurda de debugging
- dependências ocultas
- comportamento imprevisível
Curiosamente, o problema quase nunca está nos eventos em si.
Está em como eles são modelados.
Neste artigo vamos explorar três erros extremamente comuns em arquiteturas orientadas a eventos, entender por que eles acontecem e discutir abordagens mais saudáveis para construir sistemas sustentáveis no longo prazo.
1. O Que É Um Evento?
Antes de qualquer coisa, precisamos alinhar o conceito.
Definição
Um evento representa:
um fato que já aconteceu no sistema.
Ele descreve uma mudança relevante de estado.
Exemplos:
UserRegistered
PaymentApproved
SubscriptionCanceled
InvoiceGenerated
O ponto mais importante aqui é que eventos não são comandos. Eventos descrevem fatos passados.
2. Eventos não são comandos disfarçados
Esse é um dos erros mais comuns.
Muita gente escreve algo assim:
event(new SendWelcomeEmail($user));
Embora tecnicamente isso possa funcionar, semanticamente isso não é um evento.
Isso é um comando.
A intenção real da mensagem é:
"Envie um email"
e não:
"Um fato aconteceu"
Essa diferença parece pequena, mas arquiteturalmente ela é enorme.
3. Eventos saudáveis descrevem fatos
Um modelo mais saudável seria:
event(new UserRegistered($user));
Agora o sistema está comunicando:
"Um usuário foi registrado"
E diferentes partes do sistema — ou microserviços — podem reagir a isso:
- enviar email
- atualizar analytics
- criar auditoria
- emitir webhook
Os listeners passam a ser consequências do fato.
Não a razão da existência dele.
4. O Problema do Acoplamento Invisível
Aqui começa um dos maiores perigos da arquitetura orientada a eventos.
Imagine o seguinte fluxo:
event(new UserRegistered($user));
E agora imagine que esse evento dispara:
- criação de perfil
- criação de billing
- criação de tenant
- configuração de permissões
- criação de trial
- sincronização externa
À primeira vista o código parece limpo.
Mas existe um problema sério:
O fluxo real do sistema ficou invisível.
Ao olhar para o código principal, você não consegue mais saber:
- o que realmente acontece
- quantas coisas dependem daquele evento
- quais falhas podem ocorrer
- quais efeitos colaterais existem
Você perde previsibilidade.
5. O Grande Problema: fluxo principal oculto
Esse é o ponto mais importante do artigo inteiro.
Existe uma diferença enorme entre:
consequências desacopláveis
e
fluxo principal obrigatório
6. Quando Eventos Funcionam Muito Bem
Eventos brilham quando representam consequências reativas.
Por exemplo:
PaymentApproved
Após um pagamento aprovado, faz sentido reagir com:
- envio de email
- atualização de analytics
- webhook
- antifraude
- emissão fiscal
- atualização de ERP
Essas operações são naturalmente reativas.
O fato principal já aconteceu.
O restante são consequências.
7. Quando eventos começam a virar problema
Agora imagine um fluxo de cadastro de usuário.
Se o sistema depende obrigatoriamente de:
- perfil criado
- permissões criadas
- tenant criado
- trial criado
para funcionar corretamente…
talvez isso não devesse estar escondido atrás de listeners.
Porque essas operações fazem parte do núcleo do caso de uso.
8. Um Fluxo Mais Explícito
Nesses casos, normalmente é mais saudável usar orquestração explícita:
class RegisterUserService
{
public function execute()
{
$user = $this->createUser();
$this->createProfile($user);
$this->createTrial($user);
$this->createPermissions($user);
}
}
Agora o fluxo está:
- explícito
- previsível
- rastreável
- transacional
9. Uma pergunta extremamente útil
Existe uma heurística excelente para avaliar eventos:
“Se esse listener falhar, o sistema continua consistente?”
Essa pergunta separa muito bem:
- side effects de
- lógica obrigatória de negócio
Exemplo Saudável
UserRegistered -> SendWelcomeEmail
Se o email falhar:
- o usuário continua válido
- o sistema continua consistente
- o processamento pode ser refeito depois
Excelente candidato para arquitetura orientada a eventos.
Exemplo Questionável
UserRegistered -> CreateRequiredUserProfile
Se isso falhar:
- o usuário fica inconsistente
- partes do sistema quebram
- a operação principal ficou incompleta
Talvez isso não devesse ser um listener assíncrono.
10. O segundo grande erro: eventos específicos demais
Outro problema extremamente comum:
OrderCreatedWithDiscount30
ou pior:
OrderCreatedWithDiscount30AndPix
Esse tipo de modelagem normalmente indica que regras de negócio temporárias estão vazando para o nome do evento.
Isso gera:
- explosão de eventos
- acoplamento semântico
- dificuldade de evolução
- versionamento problemático
11. Eventos devem representar fatos relevantes
Uma modelagem mais saudável seria:
OrderCreated
E os detalhes ficam nos dados:
class OrderCreated
{
public function __construct(
public Order $order,
public float $discount,
public string $paymentMethod,
) {}
}
Agora o evento continua estável mesmo que as regras evoluam.
12. O terceiro grande erro: listeners virando mini sistemas
Isso acontece o tempo todo.
O listener começa simples:
class SendWelcomeEmail
{
public function handle(UserRegistered $event)
{
//
}
}
Mas o tempo passa.
E começam a surgir:
- condicionais
- integrações externas
- múltiplos serviços
- regras de negócio
- retries
- transações
- filas internas
De repente o listener virou um sistema paralelo.
13. O problema da fragmentação de negócio
Quando muita lógica fica espalhada em listeners:
- o fluxo fica difícil de seguir
- debugging vira um pesadelo
- testes ficam complexos
- onboarding piora
- observabilidade degrada
Você cria o que muitos chamam de:
business logic fragmentation
A lógica deixa de existir em um fluxo claro e passa a estar pulverizada pelo sistema inteiro.
14. Eventos trazem desacoplamento — mas com um custo
Esse é um ponto importante que muita gente ignora.
Arquitetura orientada a eventos troca:
acoplamento explícito
por
acoplamento implícito
Você ganha:
- escalabilidade
- independência
- processamento assíncrono
- flexibilidade
Mas perde:
- rastreabilidade
- previsibilidade
- simplicidade operacional
Por isso eventos não são automaticamente uma melhoria.
Eles são uma troca arquitetural.
15. Orquestração vs Coreografia
Esse debate normalmente leva a outro conceito importante.
Orquestração
Fluxo explícito:
A chama B
B chama C
C chama D
Você controla a sequência.
Coreografia
Fluxo baseado em eventos:
Evento acontece
cada sistema reage sozinho
Mais desacoplado.
Mais distribuído.
Mais difícil de visualizar.
16. Regra prática muito boa
Outra heurística extremamente útil:
“Se o fluxo precisa acontecer obrigatoriamente para a operação funcionar, talvez não devesse ser evento.”
Exemplos excelentes para eventos:
- analytics
- notificações
- emails
- webhooks
- auditoria
- integrações externas
Exemplos mais questionáveis:
- criação obrigatória de entidades core
- coordenação crítica de transações
- lógica principal do caso de uso
17. Eventos não são ruins
Isso é importante.
O objetivo não é demonizar arquitetura orientada a eventos.
Eventos são extremamente poderosos para:
- microsserviços
- integração entre bounded contexts
- event sourcing
- auditoria
- filas
- comunicação assíncrona
- sistemas distribuídos
O problema é quando eventos viram:
mecanismo oculto de workflow crítico\
Conclusão
Arquitetura orientada a eventos pode tornar sistemas extremamente elegantes.
Mas também pode transformá-los em um labirinto impossível de entender.
O segredo não está em usar mais eventos.
Está em modelar corretamente:
- o que é um fato
- o que é um comando
- o que é side effect
- o que é fluxo principal
- o que precisa de consistência imediata
- o que pode ser eventual
No fim, arquitetura madura quase sempre significa:
deixar explícito aquilo que é essencial.
E desacoplar apenas aquilo que realmente pode ser desacoplado.