Back to blog

Article

Idempotência para webhooks: guia pronto para produção

Evite efeitos duplicados causados por retries com padrões práticos de idempotência em webhooks: deduplicação, ordenação, replay, assinaturas e testes.

Article details

Published

August 19, 2026

Reading time

7 min

Main sections

9

7 min read5 FAQs

Se um webhook pode fazer retry, assuma que você vai ver o mesmo evento mais de uma vez. Isso não é um caso de borda. É o modelo de entrega normal da maioria dos provedores, e a única resposta segura é tornar seus efeitos colaterais idempotentes.

O objetivo não é entrega literalmente exactly-once. O objetivo é efeito exactly-once: uma atualização de cliente, uma fatura, uma transição de estado — mesmo que o provedor envie o payload duas vezes, três vezes ou fora de ordem.

O checklist de modo live da Stripe deixa essa expectativa explícita: handlers de webhook em produção devem tolerar notificações duplicadas e entrega fora de ordem. Em outras palavras, comportamento seguro contra duplicatas não é um diferencial. Faz parte do contrato de integração.

Rendering diagram...

Por que duplicatas acontecem

Duplicatas de webhook costumam vir de um comportamento normal de entrega:

  • timeout no lado do remetente
  • falha de rede transitória
  • crash do consumidor após processamento parcial
  • retry após um acknowledgement ambíguo

É por isso que sistemas de webhook se comportam mais como entrega at-least-once do que exactly-once. Se o consumidor não tolera essa realidade, efeitos colaterais duplicados tornam-se inevitáveis.

O que idempotência em webhooks realmente significa

Idempotência não é só "ignorar duplicatas". É um contrato sobre efeitos colaterais duráveis. O mesmo evento de entrada deveria levar ao mesmo resultado de negócio, independentemente de quantas vezes for entregue.

Isso significa que o consumidor precisa decidir qual é a unidade de trabalho:

  • um ID de evento do provedor
  • uma chave de negócio como subscription_id + billing_period
  • uma chave de idempotência gerada e atrelada à ação real

O padrão idempotent consumer é um bom modelo mental aqui: a entrega de mensagens pode se repetir, então o efeito durável também precisa ser seguro para repetir.

Padrões essenciais: escolha um e depois endureça

Fluxos diferentes precisam de defesas diferentes. Use esta comparação como a lente principal de design:

PadrãoMelhor paraForçaTrade-off
Store de deduplicação por ID de eventoProvedores que enviam identificadores estáveis de eventoSimples e eficaz para entregas repetidasDepende de identidade confiável da fonte
Unique constraint em chave de negócioTransações de negócio com chave única naturalProtege a escrita final na camada do bancoExige modelagem de domínio cuidadosa
Chaves de idempotênciaAções repetidas disparadas por cliente ou workflowFunciona bem quando retries podem vir de múltiplos atoresGeração de chave e TTL precisam ser explícitos
Inbox/outboxFluxos com múltiplos efeitos colaterais e necessidade de replayMelhora auditabilidade e recuperaçãoMais peças móveis e mais armazenamento

O default entediante mas forte costuma ser duas camadas: curto-circuitar duplicatas cedo com um registro de deduplicação e depois proteger a escrita final com uma unique constraint.

Como implementar o consumidor com segurança

Comece identificando a primeira escrita durável. É ali que a duplicata precisa ser bloqueada.

O fluxo seguro é:

  1. verificar autenticidade
  2. extrair o ID do evento ou a chave de negócio
  3. checar o store de deduplicação ou a unique constraint
  4. se já foi processado, retornar sucesso
  5. persistir o marcador do evento e executar o efeito colateral na mesma fronteira transacional, quando possível
  6. registrar metadados suficientes para replay e debugging

O design mais perigoso é marcar o evento como processado depois do efeito colateral. Se o processo cair nessa janela, um retry pode executar o efeito de novo.

Chaves de idempotência, TTLs e ordenação

Se o provedor não envia um identificador estável de evento, você pode precisar construir sua própria chave de idempotência a partir da ação de negócio. A chave deve representar o efeito que você quer proteger, não apenas o payload bruto.

A política de TTL também importa:

  • curto demais, e retries legítimos ficam fora da janela de proteção
  • longo demais, e você mantém estado desnecessário para sempre

Ordenação é a outra armadilha oculta. Muitos provedores não garantem ordem global estrita entre eventos relacionados. Se o seu consumidor assume que created sempre chega antes de updated, você vai eventualmente bater num estado impossível.

Segurança e autenticidade

Verificação de assinatura é separada da idempotência, mas precisa acontecer primeiro. Um evento assinado e duplicado continua sendo tratado como duplicata. Um evento sem assinatura ou adulterado deve ser rejeitado antes de chegar à lógica de negócio.

Se o provedor suporta proteção contra replay ou validação de timestamp, use. Autenticidade e segurança de replay fazem parte da mesma fronteira.

O guia da Stripe sobre verificação de assinatura e proteção contra replay é um bom exemplo concreto dessa fronteira: verifique o remetente, preserve o raw body e rejeite entregas velhas ou adulteradas antes de a lógica de negócio rodar.

Replay e reprocessamento

Replay não deveria ser um improviso inventado durante um incidente. Se você espera reprocessar payloads, guarde evidência suficiente para fazer isso com segurança:

  • ID do evento
  • sistema de origem
  • timestamp de recebimento
  • status de processamento
  • chave de negócio usada na deduplicação
  • correlation ID para tracing

Isso transforma replay em uma capacidade operacional, em vez de uma aposta.

Checklist de produção + casos de teste

Use este checklist antes de subir para produção:

  • confirme a semântica de retry do provedor
  • identifique a chave estável de deduplicação
  • crie o store de deduplicação antes do primeiro efeito colateral
  • torne a verificação de assinatura obrigatória
  • defina o TTL de deduplicação e a política de replay
  • logue ID do evento, status de processamento e correlation ID
  • torne os efeitos colaterais seguros para replay
  • defina como eventos fora de ordem convergem
  • decida quando replay manual ou tratamento de DLQ é necessário

Rode também estes testes:

  • mesmo evento chega duas vezes em rápida sucessão
  • mesmo evento chega após um crash entre a escrita de deduplicação e o efeito colateral
  • dois eventos mapeiam para o mesmo objeto de negócio
  • update fora de ordem chega antes do create
  • replay válido chega depois que o original já foi tratado
  • payload sem assinatura é rejeitado antes de qualquer escrita

Modos de falha comuns

O erro mais comum é tratar deduplicação como uma consulta de cache em vez de uma garantia de durabilidade. Se o registro de deduplicação não é escrito de forma atômica junto com o estado de negócio, duplicatas vão vazar.

Outro erro é assumir que o provedor vai reenviar apenas um payload idêntico para sempre. Na prática, o efeito de negócio pode importar mais do que o payload bruto.

O terceiro erro é a observabilidade ruim. Se você não consegue rastrear um webhook da ingestão ao efeito colateral, não vai saber se a duplicata é real ou se o seu próprio sistema fez retry internamente. É por isso que este tema conecta diretamente com Observabilidade para engenheiros de produto, Sistemas event-driven sem folclore e Filas não são bala de prata.

Related articles

Need help applying this?

Turn the trade-off into a practical product decision.

Se você precisa de integrações resilientes que sobrevivam a retries, replay e ao barulho real de produção, o primeiro passo é descobrir onde o seu handler atual vaza duplicatas. Comece com um get in touch.

FAQ

Common questions before committing to the pattern.

Qual é a diferença entre idempotência e deduplicação?+

Deduplicação é um mecanismo. Idempotência é o comportamento que você quer: a entrega repetida ainda produz o mesmo resultado de negócio.

Devo usar o payload do webhook como chave de deduplicação?+

Normalmente não. Prefira um ID de evento estável do provedor ou uma chave de negócio atrelada ao efeito colateral real.

Preciso de store de deduplicação e unique constraint ao mesmo tempo?+

Nem sempre, mas é um default forte. O store de deduplicação curto-circuita o trabalho repetido, e a unique constraint protege a escrita durável final.

Quanto tempo os registros de deduplicação devem viver?+

O bastante para cobrir a janela de retry do provedor e as suas necessidades de replay. O TTL certo depende do impacto no negócio e da política operacional.

E se o provedor não enviar um ID de evento estável?+

Modele a sua própria chave de idempotência a partir da ação de negócio. Em muitos sistemas, isso significa um ID de pedido, um ID de assinatura ou um período de cobrança, em vez do payload bruto.