O problema real: “salvou no banco, mas a automação não aconteceu”
Em automação, o pior bug nem sempre é o erro visível — é o silêncio. Você cria um pedido, aprova um pagamento, atualiza um status… e a etapa seguinte (notificação, emissão, CRM) simplesmente não roda.
Isso costuma acontecer quando você tenta fazer duas coisas “de uma vez”: (1) salvar no banco e (2) publicar um evento (fila, webhook, tópico) dentro do mesmo fluxo de request. Se a publicação falhar depois do commit, você fica com dado persistido e evento ausente. Se publicar antes e o commit falhar, você pode gerar evento de algo que não existe.
O que é Outbox Pattern (sem misticismo)
Outbox é uma tabela/coleção no seu banco (ex.: outbox_events) onde seu sistema registra, junto com a alteração principal, um evento a ser enviado. A sacada é transacional: se o pedido foi salvo, o evento também foi salvo — ou nenhum dos dois.
Depois, um “dispatcher” (worker, cron, serviço) lê a outbox e entrega os eventos para o destino: RabbitMQ/Kafka/SQS, webhook, ou até um endpoint que dispara um workflow no n8n/Make.
- Transação única: grava dado + evento outbox no mesmo commit
- Entrega assíncrona: um processo separado publica/entrega
- Reprocessamento: se falhar, o evento fica na outbox e tenta de novo
- Rastreabilidade: dá para auditar o que deveria ter sido enviado
Como o fluxo funciona (passo a passo)
O desenho clássico tem três partes: aplicação, outbox no banco e dispatcher. O dispatcher pode rodar a cada poucos segundos/minutos ou ficar escutando mudanças (depende da stack).
| Etapa | O que acontece | O que você ganha |
|---|---|---|
| 1) App recebe a ação | Ex.: criar pedido / atualizar status | Um ponto único de decisão |
| 2) Transação no banco | INSERT/UPDATE do dado + INSERT do evento na outbox | Consistência entre dado e evento |
| 3) Dispatcher lê outbox | Busca eventos pendentes (por status/lock) | Separação de responsabilidade |
| 4) Publica no destino | Envia para fila/webhook/iPaaS | Integrações mais resilientes |
| 5) Marca como enviado | Atualiza status/processed_at e guarda erro se falhar | Reprocesso e auditoria |
Quando vale usar (sinais práticos)
Outbox não é “padrão obrigatório”. Ele vale quando o custo de perder um evento é maior que o custo de manter um dispatcher e uma tabela a mais.
- Você já viu casos de: “pedido existe, mas não foi faturado/notificado”
- Existe mais de um consumidor do mesmo evento (ex.: CRM + estoque + BI)
- Seu workflow precisa ser reprocessável (e você quer trilha de auditoria)
- Integrações são externas e instáveis (APIs que oscilam, rate limit, timeout)
- Você precisa de escalabilidade: publicar eventos fora do request reduz latência percebida
Outbox não resolve tudo: duplicidade e ordem ainda importam
Um detalhe que pega muita gente: Outbox melhora consistência, mas não garante que o destino não receba duplicado. Retentativas podem reenviar o mesmo evento. Então, do lado do consumidor, idempotência deixa de ser “capricho” e vira pré-requisito.
Outro ponto: dependendo de como você lê a outbox e publica, eventos podem chegar fora de ordem quando há paralelismo. Se ordem for crítica (ex.: status), você precisa de chave de ordenação (por entidade) e regras claras para aceitar/descartar eventos.
Armadilhas comuns (e como não cair)
Alguns erros aparecem sempre, especialmente em automações com ferramentas no-code e um pedaço de back-end próprio.
- Sem índice e sem limpeza: a outbox cresce e vira gargalo; defina retenção e índices por status/data
- Marcar como “enviado” cedo demais: só marque depois de confirmação real (ack/resposta 2xx/publish confirmado)
- Dispatcher sem lock: dois workers publicam o mesmo evento; use lock otimista/pessimista ou claim por batch
- Payload gigante: guarde referência (ID) e versão do evento; evite duplicar documentos enormes na outbox
- Misturar regra de negócio no dispatcher: ele deve ser chato e previsível (ler, publicar, marcar, logar)
Outbox vs alternativas (visão rápida)
Dependendo da arquitetura, existem outras opções: CDC (captura de mudança no banco), publish direto em fila com transações distribuídas (geralmente caro e complexo), ou aceitar inconsistência e reconciliar depois (quando dá). Outbox costuma ser o meio-termo pragmático.
Se você trabalha com automação em n8n/Make, o padrão aparece quando existe um sistema “fonte” (ERP, e-commerce, back-end) que precisa alimentar workflows sem perder eventos — especialmente em picos.
| Abordagem | Prós | Contras |
|---|---|---|
| Publicar evento direto no request | Simples de implementar | Risco de evento perdido/duplicado em falhas; aumenta latência |
| Outbox Pattern | Boa consistência; reprocesso; auditoria | Precisa dispatcher, governança e idempotência no consumo |
| CDC (Change Data Capture) | Pouca mudança no app; captura direto do banco | Operação mais complexa; nem sempre é trivial no Brasil (stack/infra) |
Perguntas frequentes
Outbox Pattern é o mesmo que fila (RabbitMQ/Kafka/SQS)?
Dá para usar Outbox com n8n ou Make?
Outbox elimina mensagens duplicadas?
Qual o mínimo que preciso para começar com Outbox sem overengineering?
Termos relacionados
Como desenhar uma arquitetura de automação com filas, retry e idempotência (sem virar gambiarra)
Guia prático para desenhar automações resilientes: quando usar filas, como fazer retry/backoff, idempotência e DLQ. Evite duplicar pedidos, estourar rate limit e cair em loop infinito em n8n/Make/Zapier.
Ler →
Idempotency-Key: o que é e como usar em automações (sem pedido duplicado)
Entenda Idempotency-Key (chave de idempotência): por que evita duplicidade em pagamentos, pedidos e webhooks, quando usar, como gerar e como implementar em automações como n8n/Make via headers e banco.
Ler →
Como usar Dead Letter Queue (DLQ) em automações: trate falhas sem perder eventos
Guia prático de Dead Letter Queue (DLQ) para automações: quando usar, como modelar eventos, reprocessar com segurança e evitar duplicidade em n8n/Make/Zapier.
Ler →
Circuit breaker em automações (n8n/Make/Zapier): como evitar cascata de erros quando uma API cai
Guia prático para aplicar padrão circuit breaker em automações no n8n, Make ou Zapier: quando abrir/fechar, como detectar falhas, fallback, filas e alertas para não derrubar sua operação.
Ler →