Event-Driven Architecture no Node.js organiza sistemas ao redor de eventos que representam mudanças relevantes. Em vez de um serviço chamar diretamente todos os próximos passos, ele publica um fato e consumidores independentes reagem.
Essa abordagem aumenta desacoplamento e escalabilidade, mas introduz consistência eventual, duplicação de mensagens, ordenação e observabilidade distribuída. O objetivo não é tornar tudo assíncrono, e sim escolher eventos quando autonomia e resiliência justificam a complexidade.
Evento, comando e mensagem
Um comando solicita uma ação: CriarPedido. Um evento informa um fato: PedidoCriado. Mensagem é o envelope transportado por Kafka, RabbitMQ, SQS ou outro broker.
{
"id": "evt-123",
"type": "orders.order-created.v1",
"occurredAt": "2026-10-15T12:00:00Z",
"correlationId": "req-91",
"data": {
"orderId": "o-7",
"customerId": "c-2",
"totalCents": 15990
}
}Produtores e consumidores
O produtor publica um contrato e não deve conhecer todos os consumidores. Cada consumidor processa o evento conforme sua responsabilidade.
- Estoque reserva itens;
- Faturamento cria cobrança;
- Analytics atualiza métricas;
- Notificações envia confirmação.
Pub/Sub e filas
Em uma fila, uma mensagem costuma ser processada por um consumidor do grupo. Em pub/sub, vários consumidores independentes recebem o mesmo evento. Brokers oferecem combinações diferentes desses modelos.
Consistência eventual
Depois de criar um pedido, estoque e analytics podem levar alguns segundos para refletir a mudança. A interface deve comunicar estados intermediários como “processando” em vez de prometer consistência imediata.
Entrega pelo menos uma vez
A maioria dos sistemas práticos trabalha com entrega pelo menos uma vez. Isso significa que consumidores devem aceitar duplicatas.
async function consumir(event) {
await db.transaction(async trx => {
const novo = await inbox.registrar(event.id, trx);
if (!novo) return;
await projeção.aplicar(event, trx);
});
}Outbox
Persistir o estado e publicar diretamente no broker cria uma janela de falha. O padrão Outbox grava o evento na mesma transação do negócio e um worker publica depois.
Consulte Domain Events no Node.js.
Ordenação
Ordenação global reduz throughput. Preserve ordem por chave quando necessário, como orderId. Inclua versão do aggregate para detectar eventos fora de ordem.
Particionamento
Uma chave de partição deve distribuir carga sem quebrar ordem necessária. IDs muito concentrados podem criar hot partitions.
Contratos
Eventos públicos precisam de schema, documentação e compatibilidade. JSON Schema, Avro ou Protobuf podem validar payloads.
- adicione campos opcionais de forma compatível;
- não renomeie significado silenciosamente;
- versione eventos incompatíveis;
- mantenha exemplos e testes de contrato.
Veja JSON Schema no Node.js.
Retries
Falhas transitórias devem usar backoff e jitter. Erros permanentes não devem bloquear a partição indefinidamente.
const delay = Math.min(30000, 500 * 2 ** attempt) * (0.5 + Math.random());Dead Letter Queue
Após tentativas limitadas, mova a mensagem para uma DLQ com motivo, stack segura e metadados. Crie processo de análise e reprocessamento.
Backpressure
Consumidores devem controlar concorrência conforme banco, CPU e APIs externas. Mais workers não ajudam se a dependência já está saturada.
Schema Registry
Um registry centraliza versões e regras de compatibilidade. Mesmo sem ferramenta dedicada, mantenha schemas versionados no repositório e valide no CI.
Observabilidade
Monitore:
- taxa de publicação e consumo;
- lag por consumidor;
- idade da mensagem mais antiga;
- retries e DLQ;
- latência ponta a ponta;
- eventos duplicados;
- erros por tipo.
Propague traceId, correlationId e causationId.
Segurança
Use autenticação no broker, TLS, ACL por tópico ou fila e payload mínimo. Eventos podem permanecer armazenados por muito tempo; evite dados sensíveis desnecessários.
Testes
Teste serialização, schema, idempotência, mensagens fora de ordem, retry, DLQ e reprocessamento. Use um broker real em testes de integração críticos.
Quando usar
Eventos são úteis quando múltiplos consumidores reagem ao mesmo fato, integrações precisam ser resilientes ou workloads devem ser absorvidos de forma assíncrona.
Quando evitar
Uma chamada síncrona simples pode ser melhor quando o usuário precisa de resposta imediata, a operação é pequena e não há necessidade de desacoplamento.
Erros comuns
- publicar sem Outbox;
- consumidor não idempotente;
- evento usado como RPC;
- payload sem versão;
- retry infinito;
- sem DLQ operacional;
- particionamento inadequado;
- não medir lag;
- misturar dados sensíveis no evento.
Conclusão
Event-Driven Architecture no Node.js permite construir serviços autônomos e absorver picos com mensageria. O benefício depende de contratos estáveis, idempotência, consistência eventual bem comunicada e operação madura.
Comece com um fluxo onde o desacoplamento traga valor claro. Adote Outbox, retries limitados, DLQ e métricas desde o início.
Consulte o material de Martin Fowler sobre sistemas orientados a eventos e a documentação de eventos do Node.js.




