Um endpoint de webhook que passa nos testes locais quebra na primeira semana de produção. Stripe, Shopify e GitHub entregam eventos com garantia at-least-once: duplicata é certeza, ordem não tem garantia nenhuma e endpoint fora do ar vira fila de retry silenciosa. O checklist abaixo cobre idempotência, retries, assinatura e monitoramento para receber eventos sem perder nenhum.
Por que webhooks chegam duplicados?
A garantia at-least-once existe porque o remetente não distingue falha de rede de resposta perdida. Seu servidor processou o evento e o 200 se perdeu no caminho? O provedor reenvia. A Stripe mantém retries com backoff exponencial por até 3 dias; outros provedores configuram entre 3 e 20 tentativas. Duplicata é caso normal, então o handler precisa ser idempotente por construção.
Idempotência com índice único
Guarde o ID do evento fornecido pelo provedor (o event.id da Stripe) numa tabela com índice único. O fluxo seguro cabe num padrão: abra transação, insira o ID, aborte se ele já existir, processe o evento, commite. Processar e registrar na mesma transação fecha a janela em que um crash entre "processou" e "salvou" gera retrabalho.
A armadilha da ordem dos eventos
Sob retry, um charge.refunded pode chegar antes do charge.succeeded que o originou. Trate cada transição de estado como suspeita até confirmar: reembolso chegando de um pagamento que você nunca viu pede consulta à API do provedor, que detém a verdade atual. O webhook avisa que vale consultar; a API responde com o estado real.
Validação de assinatura HMAC
Endpoint público aceita payload de qualquer pessoa. Valide a assinatura HMAC que o provedor anexa (padrão do header Stripe-Signature) com comparação timing-safe: hash_equals() no PHP, Crypto.timingSafeEqual no Node. Rejeite eventos com timestamp mais velho que 5 minutos, janela de tolerância típica que bloqueia replay de payloads capturados.
Responda rápido, processe depois
Handler que executa a regra de negócio inteira antes do 200 estoura o timeout do provedor, que reenvia e dispara outra execução longa. A tempestade de duplicatas se autoalimenta. Reconheça com 200 em segundos e jogue o evento numa fila (SQS, Redis Streams, BullMQ); o worker faz o trabalho pesado com as mesmas garantias de idempotência.
Monitoramento e replay
- Taxa de sucesso de entrega por endpoint, com alerta abaixo de 99%
- Alerta quando a dead-letter queue acumula eventos
- Ferramenta de replay manual sobre o log de eventos resolve ticket de suporte e sessão de debugging
Emitindo webhooks próprios
No lado de envio, assine cada payload, documente a política de retry, exponha log de eventos com status de entrega e suporte rotação de secret sem downtime. O consumidor que depende do seu webhook precisa das quatro coisas; sem elas, cada incidente vira ticket.
Curtiu o conteúdo?
Construo produtos web e soluções com IA do jeito certo — arquitetura sólida, código sustentável e entrega real.
Vamos conversar