Início › Guias › Confiabilidade de automações (webhook, retry, filas, deduplicação)
Guia

Como fazer idempotência em automações com webhook (e parar de duplicar pedidos, notas e leads)

Atualizado em 2026-09-23 · por Redação Automação Hoje
Como fazer idempotência em webhook para evitar pedidos duplicados na automação
Resposta rápida: Idempotência é a técnica de garantir que a mesma requisição (ou evento) processe “uma vez só”, mesmo que o webhook seja reenviado por timeout, retry ou clique duplo. Na prática: você cria uma chave única por evento, registra essa chave num storage (banco/planilha/cache) e, se ela reaparecer, você ignora ou retorna o mesmo resultado sem repetir ações como cobrar, emitir nota ou criar lead.
· espaço publicitário ·
Em resumo
  • Webhooks são reenviados por padrão em muitos sistemas quando há timeout/erro: duplicidade é “comportamento esperado” se você não se proteger.
  • Idempotência não é só “tirar duplicado depois”; é desenhar o fluxo para ser seguro ao repetir.
  • A chave idempotente precisa ser determinística (mesmo evento → mesma chave) e rápida de consultar.
  • O ponto crítico é onde você tem efeito colateral: cobrança, pedido, nota, mensagem WhatsApp, criação de ticket.
  1. 1) Descubra qual é o evento (e de onde vem a duplicidade)

    Antes de mexer no fluxo, confirme o motivo do replay: timeout no endpoint, política de retry do provedor, usuário clicando duas vezes, fila do gateway, ou webhook sendo disparado em “update” e “create”. Se você não sabe “qual evento é o mesmo evento”, não existe chave idempotente que resolva.

  2. 2) Defina a chave idempotente (idempotency key)

    Use um identificador que venha do sistema de origem (ex.: event_id, message_id, payment_id, order_id + status). Se não existir, construa: normalize campos estáveis (tipo do evento + id do objeto + timestamp do evento arredondado) e gere um hash. Evite usar horário de chegada no webhook (isso muda).

  3. 3) Escolha onde guardar a chave (storage de deduplicação)

    Você precisa de um lugar consultável e persistente. Opções comuns: banco SQL (tabela de eventos processados), Redis/cache com TTL (para janelas curtas), ou uma planilha/tabela simples quando o volume é baixo. O importante é ter consulta rápida e condição de unicidade (unique) quando possível.

  4. 4) Faça a checagem logo no começo do fluxo

    A primeira coisa após receber o webhook deve ser: “já vi essa chave?”. Se sim, encerre com sucesso (200/OK) e, se o sistema esperar resposta, devolva o mesmo payload/resultado (quando aplicável). Se não, registre a chave e siga.

  5. 5) Trave contra corrida (race condition)

    Dois webhooks iguais podem chegar quase ao mesmo tempo. Se você fizer só um “SELECT antes” sem travar, ambos passam. Prefira: inserir com chave única (e se der conflito, tratar como duplicado) ou usar lock/SETNX (no Redis). Isso é o que separa deduplicação “bonitinha” de deduplicação que aguenta produção.

  6. 6) Modele o comportamento: ignorar, reprocessar ou “retornar o mesmo resultado”

    Nem todo duplicado deve ser descartado. Para cobrança/pedido/emissão de nota, o padrão é não repetir efeito colateral. Para um webhook de “consulta de status”, pode ser ok reprocessar. Em muitos casos, o melhor é responder como se tivesse processado, mas sem executar novamente.

  7. 7) Defina janela de retenção (TTL) e auditoria

    Guarde chaves por tempo compatível com o negócio: para pagamentos e pedidos, geralmente você quer dias ou meses (depende de chargeback, reconciliação e disputa). Quando não der para guardar “para sempre”, registre também logs/auditoria do processamento para provar o que aconteceu.

O que acontece sem idempotência (o roteiro do desastre)

Você recebe um webhook de pedido pago. Seu fluxo manda mensagem para o cliente, cria nota no ERP e dispara separação no estoque.

O provedor reenviou o webhook porque seu endpoint demorou a responder (ou porque caiu por 2 segundos). Resultado: duas notas, duas separações, duas mensagens. A equipe “resolve no braço”, e o custo real fica invisível até estourar.

Idempotência é o cinto de segurança: você não planeja bater, mas o impacto diminui quando acontece.

Como escolher uma chave idempotente que não te traia

A melhor chave é a que já existe no evento: um event_id único gerado pelo sistema de origem. Se não existir, você precisa construir uma chave que represente o “mesmo acontecimento”.

Regra prática: a chave deve mudar quando o evento for realmente diferente, e ficar igual quando for replay do mesmo evento.

  • Boas chaves (exemplos): payment_id; event_id; order_id + tipo_evento; message_id.
  • Chaves perigosas: timestamp de chegada; número incremental do seu próprio fluxo; hash do payload inteiro (pequenas variações quebram).
  • Quando há “update”: inclua versão/estado (ex.: order_id + status_atual) para não bloquear transições legítimas.

Padrões de implementação (com e sem banco)

Você não precisa de uma arquitetura gigantesca para começar, mas precisa de consistência. Abaixo, o que costuma funcionar na prática — do mais robusto ao mais simples.

AbordagemComo funcionaQuando usarRisco/limite
Banco SQL com chave únicaInsere (idempotency_key) em tabela com UNIQUE; conflito = duplicadoProdução, alto impacto (cobrança/nota/pedido)Exige banco e cuidado com transações
Redis/Cache com SETNX + TTLCria lock/chave se não existir; se existir, bloqueia repetiçãoAlta taxa de eventos, janela curta de dedupeSe TTL for curto demais, duplicidade volta
Planilha/DB no-code simplesBusca chave; se não existir, grava e continuaBaixo volume e baixo riscoRace condition e performance; precisa disciplina
Deduplicação pós-fatoDeixa duplicar e tenta “consertar” depoisQuase nunca é o idealVocê já sofreu o efeito colateral

Onde a maioria erra: registrar a chave tarde demais

O erro clássico é checar duplicidade depois de já ter criado o lead, emitido nota ou enviado WhatsApp. A checagem precisa ser no início, antes do efeito colateral.

Se seu fluxo faz múltiplas ações, pense em idempotência por etapa: às vezes você quer impedir duplicação de cobrança, mas permitir reenvio de mensagem (ou o inverso).

Checklist rápido para webhooks resilientes

Se você só aplicar idempotência, já melhora muito. Mas um webhook confiável costuma precisar de mais três coisas: timeout decente, retries com backoff e logs úteis.

  • Responder rápido (200) quando possível; fazer processamento pesado em segundo plano se sua stack permitir.
  • Tratar 429/rate limit com retry/backoff (sem “loop infinito”).
  • Guardar: idempotency_key, timestamp, status (processado/erro), e um identificador do fluxo que processou.
  • Alertar quando a taxa de duplicados ou erros subir (é sinal de instabilidade a montante ou a jusante).

Perguntas frequentes

Idempotência é a mesma coisa que deduplicação?
São parecidas, mas não iguais. Deduplicação pode ser “limpar duplicados” depois. Idempotência é uma propriedade do processamento: repetir a mesma entrada não muda o resultado e não repete efeitos colaterais.
Qual status devo responder quando o webhook é duplicado?
Na maioria dos casos, responda sucesso (200/OK) para parar novos retries do provedor, mas sem repetir a ação. Se o sistema exige um corpo de resposta específico, devolva o mesmo resultado do processamento original (quando fizer sentido).
Como lidar com dois webhooks idênticos chegando ao mesmo tempo?
Você precisa de um mecanismo atômico: UNIQUE no banco (insert e tratar conflito) ou um lock (ex.: SETNX no Redis). Só “consultar e depois inserir” pode falhar por corrida.
E quando o evento é parecido, mas não é duplicado (ex.: pedido mudou de status)?
A chave idempotente deve representar o que você quer tornar único. Se status é parte do evento, inclua status (ou uma versão) na chave. Assim, “pedido 123 pago” e “pedido 123 enviado” não se bloqueiam entre si.

Leia também