# ADR: EventBridge vs Kafka/MSK para Processamento de Pedidos

Este ADR avalia EventBridge e Amazon MSK como backbone de eventos para um sistema de processamento de pedidos, considerando throughput, ordenação, replay e carga operacional. A decisão é fundamentada em trade-offs reais entre managed simplicity e controle de plataforma, com consequências diretas em custo, operabilidade e garantias de entrega.

- URL: https://fernando.moretes.com/studies/adr-event-driven-eventbridge-vs-kafka

- Markdown: https://fernando.moretes.com/studies/adr-event-driven-eventbridge-vs-kafka/study.md?lang=pt

- Type: Decisão (ADR)

- Company: Order processing (cenário)

- Domain: Event-driven

- Status: accepted

- Date: 2026-01-25

- Tags: event-driven, eventbridge, kafka, msk, order-processing, adr, aws, messaging

- Reading time: 7 min

---

Escolher o backbone de eventos errado em um sistema de pedidos não é um problema de preferência tecnológica — é um risco de negócio. EventBridge e MSK resolvem problemas parecidos na superfície, mas divergem profundamente em garantias de entrega, throughput, ordenação e custo operacional. Este ADR documenta o raciocínio que levou à decisão e os trade-offs que qualquer arquiteto precisa entender antes de fazer essa escolha.

## Ficha do Cenário

- **Sistema:** Plataforma de processamento de pedidos (e-commerce / marketplace)
- **Domínio:** Event-driven architecture
- **Volume estimado:** 5.000–50.000 pedidos/hora em operação normal; picos de 10x em datas comemorativas (estimativa)
- **Consumidores de eventos:** Estoque, pagamentos, notificações, fraude, analytics, fulfillment
- **Requisitos críticos:** Ordenação por pedido, replay para reprocessamento, at-least-once delivery, auditoria
- **Cloud:** AWS (região única, multi-AZ)
- **Stack existente:** Lambda, ECS/Fargate, RDS Aurora, S3, CloudWatch
- **Status da decisão:** Aceita

## Contexto e Forças em Jogo

O sistema de pedidos é o núcleo operacional da plataforma. Cada transição de estado de um pedido — criado, pago, separado, despachado, entregue, cancelado — precisa ser propagada de forma confiável para múltiplos consumidores downstream. Um erro nessa propagação pode resultar em cobrança dupla, estoque incorreto, falha de notificação ao cliente ou inconsistência no sistema de fraude.

A equipe de engenharia tem experiência sólida com AWS managed services e Lambda, mas não possui histórico operacional com Kafka. O time de plataforma tem dois engenheiros sênior dedicados à infraestrutura. A pressão de negócio é por time-to-market rápido, mas o CTO sinalizou que qualquer incidente de perda de pedido tem custo político alto.

As forças que moldam esta decisão são:

- **Ordenação**: pedidos individuais precisam ser processados em sequência. Um evento de `order.cancelled` não pode ser processado antes de `order.paid` para o mesmo `orderId`.
- **Throughput**: o volume atual não é extremo, mas os picos de Black Friday e datas sazonais exigem elasticidade real.
- **Replay**: a equipe de analytics e o time de fraude precisam reprocessar eventos históricos quando modelos mudam ou bugs são corrigidos.
- **Carga operacional**: com um time pequeno, cada hora gasta em tuning de brokers é uma hora a menos em features.
- **Custo**: MSK tem custo fixo de infraestrutura independente de uso; EventBridge cobra por evento publicado.
- **Integração com o ecossistema AWS**: o stack existente é 100% AWS; integrações nativas reduzem código de cola.

## Por Que Esta Decisão É Não-Trivial

A tentação comum é tratar EventBridge como "Kafka gerenciado mais simples". Essa analogia é perigosa. EventBridge é um **event router** baseado em regras — ele roteia eventos de fontes para destinos com base em padrões de conteúdo. Kafka (e MSK) é um **log distribuído de commits** — ele armazena eventos de forma durável, ordenada e permite múltiplos consumidores independentes lerem no seu próprio ritmo.

Essas diferenças têm implicações concretas:

**Ordenação**: EventBridge não garante ordenação entre eventos. Para um sistema de pedidos onde a sequência `created → paid → shipped` é semanticamente crítica, isso exige que os consumidores implementem lógica de ordenação própria ou que a aplicação tolere eventos fora de ordem. MSK com particionamento por `orderId` garante ordenação dentro da partição — o que é exatamente o que precisamos.

**Replay**: EventBridge Archive permite replay de eventos, mas com limitações — o replay é para o mesmo destino e não suporta filtragem granular por consumidor. MSK retém o log por período configurável (dias a semanas) e qualquer consumer group pode reposicionar seu offset para qualquer ponto no tempo, independentemente dos outros. Para o time de analytics que precisa reprocessar 30 dias de eventos sem afetar o consumer de pagamentos, MSK é estruturalmente superior.

**Fan-out e acoplamento**: EventBridge brilha no fan-out desacoplado — você adiciona uma nova regra e um novo destino sem tocar no produtor. MSK requer que novos consumidores criem seus próprios consumer groups, o que é igualmente desacoplado mas exige mais configuração inicial.

**Throughput e latência**: EventBridge tem throughput padrão de 10.000 eventos/segundo por região (com soft limits ajustáveis via suporte), latência tipicamente abaixo de 1 segundo mas sem SLA de latência publicado. MSK suporta throughput de centenas de MB/s com latência de milissegundos em configurações adequadas. Para o volume atual do sistema, ambos são suficientes — mas MSK tem headroom muito maior.

O ponto central é: **EventBridge é a escolha certa quando o problema é roteamento e integração de serviços; MSK é a escolha certa quando o problema é streaming de dados com ordenação, replay e múltiplos consumidores independentes**. Processamento de pedidos é o segundo caso.

## Opções Avaliadas

### Amazon EventBridge (Event Bus)

**Pros**
- Zero overhead operacional — totalmente serverless e gerenciado pela AWS
- Integração nativa com 200+ serviços AWS e SaaS partners
- Schema Registry integrado para governança de contratos de eventos
- Fan-out desacoplado via regras — adicionar consumidor não requer mudança no produtor
- Custo proporcional ao uso — ideal para volumes baixos e irregulares

**Cons**
- Sem garantia de ordenação entre eventos do mesmo pedido
- Replay via Archive tem limitações: sem filtragem por consumer, replay vai para destino original
- Retenção máxima de eventos via Archive: indefinida, mas replay tem janela operacional limitada
- Sem conceito de consumer group — múltiplos consumidores exigem múltiplas regras e targets
- Throughput default de 10k eventos/s por região (soft limit) pode ser insuficiente em picos extremos

**Verdict:** Adequado para integração de serviços e notificações; insuficiente como backbone de pedidos com requisito de ordenação e replay granular

### Amazon MSK (Managed Streaming for Apache Kafka)

**Pros**
- Ordenação garantida por partição — particionamento por orderId garante sequência de estados
- Replay nativo e granular — qualquer consumer group reposiciona offset independentemente
- Throughput de centenas de MB/s — headroom real para crescimento
- Retenção configurável (dias a semanas) — log imutável como fonte de verdade
- Consumer groups independentes — analytics, fraude, pagamentos leem sem interferência mútua

**Cons**
- Custo fixo de infraestrutura independente de uso — brokers cobrados por hora
- Curva de aprendizado operacional: partições, replication factor, consumer lag, offset management
- Sem integração nativa direta com Lambda via trigger (requer MSK Event Source Mapping — disponível mas com limitações de throughput)
- Requer planejamento de partições upfront — reparticionamento posterior é complexo
- Monitoramento de consumer lag exige instrumentação adicional (CloudWatch MSK metrics)

**Verdict:** Escolha correta para o backbone de pedidos — ordenação, replay e múltiplos consumers independentes são requisitos de primeira classe atendidos nativamente

### Arquitetura Híbrida: MSK + EventBridge

**Pros**
- MSK como backbone de pedidos (ordenação + replay); EventBridge para notificações e integrações externas
- Cada tecnologia usada no seu ponto forte
- Integração com SaaS e serviços externos via EventBridge sem expor MSK

**Cons**
- Complexidade operacional dobrada — dois sistemas de mensageria para manter
- Bridge entre MSK e EventBridge requer Lambda ou Connector — ponto adicional de falha
- Custo combinado mais alto no curto prazo

**Verdict:** Válido como evolução futura quando integrações externas escalarem; prematuro como ponto de partida

## Decisão de Arquitetura

**Status:** accepted

**Contexto**

O sistema de processamento de pedidos requer um backbone de eventos que garanta ordenação por pedido, suporte replay granular por consumer group, sustente picos de throughput sazonais e opere com um time de plataforma pequeno. O stack existente é 100% AWS.

**Decisão**

Adotar Amazon MSK (Kafka gerenciado) como backbone de eventos para o sistema de pedidos. Utilizar MSK Serverless na fase inicial para reduzir overhead de capacity planning, com migração para MSK Provisioned quando o volume justificar controle granular de partições e throughput. Particionamento por `orderId` para garantir ordenação. Retenção de log de 7 dias como padrão, extensível para 30 dias para o tópico de pedidos. EventBridge permanece no stack para integrações com serviços externos e notificações, alimentado por um consumer MSK dedicado.

**Consequências**
- ✅ Ordenação por pedido garantida nativamente via particionamento por orderId
- ✅ Replay independente por consumer group — analytics e fraude podem reprocessar sem afetar pagamentos
- ✅ Headroom de throughput real para crescimento orgânico e picos sazonais
- ✅ Log imutável como fonte de verdade auditável para compliance e debugging
- ⚠️ Custo fixo de infraestrutura MSK mesmo em períodos de baixo volume (mitigado por MSK Serverless inicialmente)
- ⚠️ A equipe precisará adquirir competência operacional em Kafka: consumer lag monitoring, offset management, rebalancing

## Detalhes de Implementação e Riscos Operacionais

**Estratégia de particionamento**: A chave de partição deve ser o `orderId`. Isso garante que todos os eventos de um pedido específico sejam escritos na mesma partição e, portanto, consumidos em ordem. O número inicial de partições para o tópico `orders` deve ser calculado com base no throughput de pico esperado dividido pelo throughput por partição sustentável (tipicamente 1-10 MB/s dependendo do tamanho da mensagem e configuração do broker). Para o volume estimado, 12 partições é um ponto de partida razoável — permite até 12 instâncias paralelas de um consumer group sem rebalancing.

**Retenção e replay**: Configurar `retention.ms` para 604800000 (7 dias) no tópico principal. Para o tópico de pedidos, considerar 30 dias dado o requisito de reprocessamento do time de analytics. O replay é operacionalizado via reset de offset do consumer group — o time deve ter runbooks documentados para essa operação, incluindo como pausar o consumer de produção antes do replay para evitar processamento duplicado não intencional.

**Consumer criticality tiers**: Nem todos os consumers têm o mesmo SLA. Pagamentos e estoque são críticos — devem rodar em ECS/Fargate com auto-scaling baseado em consumer lag (métrica `EstimatedMaxTimeLag` no CloudWatch MSK). Notificações e analytics podem usar Lambda via MSK Event Source Mapping, aceitando latência maior em troca de menor custo operacional.

**Dead Letter Queue**: Cada consumer deve ter uma DLQ (SQS) para mensagens que falham após N tentativas. O schema de retry deve ser exponential backoff com jitter. Mensagens na DLQ devem gerar alertas no CloudWatch e ter processo de reprocessamento manual documentado.

**Risco de rebalancing**: Em consumers ECS, o rebalancing do Kafka pode causar pausas de processamento de segundos a dezenas de segundos dependendo do tamanho do grupo e da estratégia de rebalancing. Configurar `partition.assignment.strategy=CooperativeStickyAssignor` para minimizar o impacto. Monitorar `RebalanceLatency` e alertar se exceder thresholds aceitáveis.

**MSK Serverless vs Provisioned**: MSK Serverless simplifica o início, mas tem limitações: throughput máximo de 200 MB/s de escrita e 400 MB/s de leitura por cluster, sem controle de número de partições (gerenciado automaticamente), e custo por unidade de capacidade que pode ser mais alto que Provisioned em volumes altos. A migração para Provisioned deve ser planejada quando o volume mensal de dados processados tornar o custo por unidade de capacidade desfavorável — tipicamente acima de alguns TB/mês (estimativa).

## Arquitetura Resultante: Backbone MSK para Processamento de Pedidos

Fluxo de eventos desde a criação do pedido até os consumidores downstream, com MSK como backbone central, DLQs por consumer e EventBridge para integrações externas.

### 🛒 Order Service

- Order API ECS/Fargate (compute)
- Orders DB RDS Aurora (data)

### 📨 MSK Backbone

- Amazon MSK orders topic 12 partitions / key=orderId (messaging)

### ⚙️ Critical Consumers (ECS/Fargate)

- Payments Consumer ECS/Fargate (compute)
- Inventory Consumer ECS/Fargate (compute)
- Fraud Consumer ECS/Fargate (compute)

### ⚡ Async Consumers (Lambda)

- Notifications Consumer Lambda (MSK trigger) (compute)
- Analytics Consumer Lambda (MSK trigger) (compute)

### 🔀 External Integration

- EventBridge Bridge Lambda Consumer (compute)
- Amazon EventBridge Custom Event Bus (messaging)
- External SaaS (CRM, ERP, etc.) (external)

### 🚨 Error Handling

- DLQ Payments SQS (messaging)
- DLQ Inventory SQS (messaging)
- DLQ Generic SQS (messaging)
- CloudWatch Lag Alerts (security)

### 📦 Downstream Storage

- S3 Analytics Lake (storage)

### Fluxos

- order-api -> order-db: persiste pedido
- order-api -> msk-cluster: publica evento (key=orderId)
- msk-cluster -> payments-consumer: consumer group: payments
- msk-cluster -> inventory-consumer: consumer group: inventory
- msk-cluster -> fraud-consumer: consumer group: fraud
- msk-cluster -> notif-consumer: MSK Event Source Mapping
- msk-cluster -> analytics-consumer: MSK Event Source Mapping
- msk-cluster -> eb-bridge: consumer group: external
- eb-bridge -> eventbridge: publica para bus externo
- eventbridge -> external-saas: regras de roteamento
- payments-consumer -> dlq-payments: falha após retries
- inventory-consumer -> dlq-inventory: falha após retries
- notif-consumer -> dlq-generic: falha após retries
- analytics-consumer -> s3-analytics: escreve no data lake
- msk-cluster -> cloudwatch: métricas de lag

## Comparativo Técnico: EventBridge vs MSK para Pedidos
| Critério | Dimensão | EventBridge | Amazon MSK | Relevância para Pedidos |
| --- | --- | --- | --- | --- |
| Ordenação | Sem garantia | Garantida por partição | 🔴 Crítico — sequência de estados é obrigatória | — |
| Replay | Archive com limitações de filtragem | Offset reset por consumer group | 🔴 Crítico — analytics e fraude precisam de replay independente | — |
| Throughput | 10k eventos/s default (soft limit) | Centenas de MB/s | 🟡 Relevante para picos sazonais | — |
| Overhead operacional | Mínimo — serverless | Moderado — partições, lag, rebalancing | 🟡 Relevante — time pequeno | — |
| Custo | Por evento publicado | Fixo por broker-hora + armazenamento | 🟡 MSK Serverless mitiga custo fixo inicial | — |
| Fan-out desacoplado | Nativo via regras | Via consumer groups | 🟢 Ambos adequados | — |
| Integração AWS nativa | 200+ serviços sem código | Via Lambda/ECS consumers | 🟢 EventBridge superior para integrações externas | — |
| Retenção de log | Archive indefinido (mas replay operacional limitado) | Configurável: horas a semanas | 🔴 MSK superior para auditoria e reprocessamento | — |

## Análise Well-Architected

- **security**: MSK suporta autenticação via IAM (MSK IAM Auth), TLS em trânsito e criptografia em repouso com KMS. Consumer groups isolados por IAM policy garantem que o consumer de analytics não possa escrever no tópico de pedidos. VPC-only access elimina exposição pública. EventBridge bridge usa IAM role com permissões mínimas.
- **reliability**: MSK multi-AZ com replication factor 3 garante durabilidade mesmo com falha de um broker. DLQs por consumer evitam que falhas em um downstream bloqueiem outros. Consumer lag monitoring com alertas garante detecção precoce de consumers atrasados. MSK Serverless tem SLA de 99.9% de disponibilidade.
- **performance**: Particionamento por orderId distribui carga uniformemente e garante paralelismo. Consumers críticos em ECS/Fargate com auto-scaling baseado em consumer lag respondem a picos em minutos. Batch size e fetch.min.bytes configuráveis para otimizar throughput vs latência por consumer.
- **cost**: MSK Serverless na fase inicial evita custo fixo de brokers provisionados. Migração para Provisioned quando volume justificar. Retenção de 7 dias como padrão — tópicos de analytics com 30 dias têm custo de armazenamento incremental. Consumers Lambda para workloads async reduzem custo de ECS.
- **sustainability**: MSK Serverless escala para zero em períodos de baixo uso, reduzindo consumo de recursos ociosos. Retenção de log configurável evita armazenamento desnecessário de dados históricos além do período de utilidade operacional.

> **Minha Perspectiva Sênior:** Eu vejo esse debate EventBridge vs Kafka com frequência, e o erro mais comum é enquadrar a decisão como "qual é mais simples de operar" em vez de "qual resolve os requisitos funcionais corretamente". EventBridge é uma ferramenta excelente — eu a uso extensivamente para integrações entre serviços, notificações e fan-out de eventos de domínio onde ordenação não é crítica. Mas para um backbone de pedidos, a falta de ordenação garantida não é um detalhe de implementação — é uma falha estrutural.

O que me preocupa mais nesse tipo de decisão não é a escolha da tecnologia em si, mas a tendência de subestimar o custo de **não ter replay**. Todo sistema de pedidos vai precisar de replay em algum momento — um bug no consumer de estoque, uma mudança no modelo de fraude, uma migração de schema. Se você construiu sobre EventBridge e não planejou o Archive com cuidado, esse replay vai ser doloroso ou impossível. Com MSK, é uma operação de 5 minutos com um runbook.

Sobre a carga operacional: sim, Kafka tem curva de aprendizado. Mas MSK Serverless reduziu significativamente o overhead de operação para casos de uso como esse. O time não precisa gerenciar brokers, ZooKeeper ou replication manualmente. O que precisa é entender consumer groups, offsets e lag monitoring — e isso é conhecimento que vale a pena ter em qualquer time que trabalha com sistemas distribuídos.

Minha recomendação prática: comece com MSK Serverless, invista 2 sprints em runbooks e observabilidade de lag, e use EventBridge apenas para o que ele faz melhor — integração com serviços externos e notificações. A arquitetura

## Veredicto

Amazon MSK é a escolha correta para o backbone de eventos de um sistema de processamento de pedidos. Os três requisitos que definem essa decisão — ordenação por pedido, replay granular por consumer e retenção de log como fonte de verdade — são atendidos nativamente pelo modelo de log distribuído do Kafka e não têm equivalente funcional no EventBridge.

EventBridge não é descartado: ele permanece no stack como camada de integração para serviços externos e SaaS, alimentado por um consumer MSK dedicado. Essa separação de responsabilidades é a arquitetura correta — não uma concessão.

O custo operacional de MSK é real e não deve ser minimizado. A mitigação é MSK Serverless na fase inicial e investimento deliberado em observabilidade de consumer lag e runbooks operacionais. Um time que entende offsets e consumer groups é um time mais resiliente, independentemente da tecnologia de mensageria que usar no futuro.

A lição transferível: **a escolha entre um event router e um log distribuído não é sobre preferência ou simplicidade — é sobre quais garantias semânticas o seu domínio exige**. Identifique essas garantias primeiro; a tecnologia segue.

## Referências

- [Amazon EventBridge — Official Documentation](https://aws.amazon.com/eventbridge/)
- [Amazon MSK (Managed Streaming for Apache Kafka) — Official Documentation](https://aws.amazon.com/msk/)

## Fontes do caso

- [AWS — Amazon EventBridge](https://aws.amazon.com/eventbridge/)
- [AWS — Amazon MSK](https://aws.amazon.com/msk/)
