Webhooks vs polling: escolhendo a abordagem certa de integração
Webhooks vs polling: entenda como cada abordagem afeta latência, falhas, limites de taxa e os padrões de retentativa e replay que mantêm os dados sincronizados.

Que problema estamos resolvendo quando sincronizamos dados?
Sincronizar soa como “fazer atualizações aparecerem rápido”, mas o trabalho real é mais difícil: fazer dois sistemas concordarem sobre o que é verdade, mesmo quando mensagens chegam atrasadas, duplicadas ou faltando.
Em webhooks vs polling, a diferença é como você descobre que algo mudou.
Um webhook é push. O Sistema A chama seu endpoint quando um evento acontece (por exemplo, “payment_succeeded”). Polling é pull. Seu sistema pergunta ao Sistema A em um cronograma: “tem algo novo desde a última vez?”
Manter sistemas em sincronia geralmente significa acompanhar tanto eventos quanto estado. Eventos dizem o que aconteceu. Estado diz como o registro está agora. O momento importa porque integrações raramente chegam em ordem perfeita. Um evento “updated” pode chegar antes do “created”, pode chegar duas vezes ou pode nunca chegar.
O objetivo é ter dados corretos, não apenas dados recentes. “Correto” significa que você não perde mudanças, não aplica a mesma mudança duas vezes, consegue se recuperar após downtime sem limpeza manual e pode provar o que processou e quando.
Um exemplo prático: seu provedor de pagamentos envia um webhook como “payment_succeeded”. Seu app cria um pedido e marca como pago. Se seu endpoint de webhook ficar fora do ar por pouco tempo, você pode nunca ver esse evento. Um job de polling que pergunta por pagamentos atualizados “desde ontem” pode reconciliar a lacuna e corrigir o estado do pedido.
A maioria das integrações reais acaba usando ambos: webhooks para velocidade e polling para backfill e verificação. O método é menos importante que as proteções ao redor dele.
Latência e atualidade: quão rápido as atualizações realmente chegam
Quando as pessoas comparam webhooks vs polling, muitas vezes querem dizer uma coisa: com que rapidez seu app percebe uma mudança em outro lugar. Essa atualidade não é só agradável — afeta tickets de suporte, trabalho duplicado e se os usuários confiam no que veem.
O polling tem atraso embutido porque você só pergunta num cronograma. Se você faz polling a cada 5 minutos, uma atualização pode chegar em qualquer momento entre alguns segundos até quase 5 minutos de atraso, além do tempo de resposta da API. Polling mais frequente melhora a atualidade, mas aumenta chamadas de API, custo e chances de bater em limites de taxa.
Webhooks podem parecer quase em tempo real porque o provedor empurra um evento assim que algo acontece. Mas eles não são instantâneos nem garantidos. Provedores podem agrupar eventos, tentar novamente mais tarde ou pausar a entrega. Seu sistema também adiciona atraso (filas, bloqueios no banco, deploys). Uma expectativa mais realista é: rápido quando tudo está saudável, eventualmente consistente quando não está.
O formato do tráfego importa. Polling gera carga constante e previsível. Webhooks são em rajadas: uma hora de pico pode enviar centenas de eventos em um minuto e depois nada por um tempo. Se você aceitar webhooks, assuma picos e planeje enfileirar eventos para processá-los em um ritmo controlado.
Antes de projetar qualquer coisa, escolha uma janela de atualidade alvo:
- Segundos: notificações ao usuário, chat, status de pagamento
- Minutos: ferramentas de suporte, visões administrativas, relatórios leves
- Horas: reconciliação noturna, analytics de baixa prioridade
Se o time de vendas precisa que novos leads apareçam em 1 minuto, webhooks chegam lá. Um “polling de segurança” a cada poucas horas ainda pode pegar eventos perdidos e confirmar o estado final.
Modos de falha que você verá na produção
A maioria das integrações falha de formas chatas e repetíveis. A surpresa não é que algo quebre — é que quebre silenciosamente. Velocidade é fácil de discutir. Confiabilidade é onde mora o trabalho de verdade.
Falhas em polling costumam parecer “não vimos a atualização”, mesmo quando o código parece certo. Timeouts podem cortar uma requisição no meio. Respostas parciais podem passar se você só checar HTTP 200 e não validar o corpo. Mudanças de paginação são comuns: uma API muda a ordenação, altera regras de página ou troca de números de página para cursores, e você acaba pulando ou relendo itens. Outro erro clássico é filtrar por “updated_since” usando o relógio local, e então perder atualizações quando os relógios divergem ou o provedor usa outro campo de timestamp.
Webhooks falham de modo diferente. A entrega costuma ser “pelo menos uma vez”, então provedores tentam novamente em falhas de rede e você verá duplicatas. Se seu endpoint ficar fora por 10 minutos, pode receber uma rajada de eventos antigos mais tarde. Problemas de validação de assinatura também são frequentes: um segredo rotaciona, você valida o payload errado, ou um proxy modifica cabeçalhos e, de repente, eventos válidos parecem inválidos.
O modo de falha compartilhado em ambas as abordagens é duplicatas e entrega fora de ordem. Assuma que você receberá o mesmo evento mais de uma vez, eventos chegando atrasados, fora de ordem, e payloads sem campos esperados.
Quase nunca se tem “exatamente uma vez”. Projete para “pelo menos uma vez” e torne o tratamento seguro. Armazene uma chave de idempotência (ID do evento ou versão do objeto do provedor), ignore repetições e aplique atualizações apenas se forem mais novas do que o que já salvou. Também registre o que recebeu e o que fez com isso, para que você possa reproduzir com confiança em vez de adivinhar.
Limites de taxa e custo: controlar o uso da API
Limites de taxa são onde webhooks vs polling deixa de ser teoria e vira problema de orçamento e confiabilidade. Cada requisição extra custa tempo e dinheiro, e pode prejudicar sua relação com o provedor.
Polling consome cotas porque você paga por checar mesmo quando nada mudou. Piora quando limites são por usuário ou por token: 1.000 clientes fazendo polling a cada minuto pode parecer um ataque, mesmo que cada cliente esteja “comportado”. Polling também multiplica chamadas facilmente (listar endpoints e depois buscar detalhes para cada item), e é assim que você chega no teto inesperadamente.
Webhooks geralmente reduzem chamadas de API, mas criam pressão em rajadas. Um provedor pode entregar milhares de eventos de uma vez após uma queda, importação em massa ou lançamento de produto. Alguns vão fazer throttle com 429s, outros vão tentar repetidas vezes, e alguns podem descartar eventos se seu endpoint estiver lento. Seu lado precisa de backpressure: aceite rapidamente, enfileire o trabalho e processe em um ritmo seguro.
Para reduzir chamadas sem perder correção, foque em alguns padrões que funcionam na prática:
- Sync incremental usando timestamps “updated since” ou tokens de mudança
- Filtragem no servidor (inscreva-se apenas nos tipos de evento que precisa)
- Leitura e escrita em lote (busque detalhes em chunks, escreva em bulk)
- Cache de dados de referência estáveis (planos, listas de status, perfis de usuário)
- Separar “tempo-real” de “reporting” (caminho rápido vs jobs noturnos)
Planeje picos antes que aconteçam. Mantenha um modo de backfill dedicado que rode mais devagar, respeite cotas e possa ser pausado e retomado.
Escolhendo a abordagem certa: um guia simples de decisão
A escolha webhooks vs polling geralmente se resume a isto: você precisa de velocidade ou de uma forma simples e previsível de obter atualizações mesmo quando o fornecedor é pouco confiável?
Polling é muitas vezes o padrão melhor quando o terceiro não oferece webhooks, ou quando seu fluxo de trabalho tolera atraso. Também é fácil de raciocinar se você só precisa de uma sincronização diária ou horária e a API tem um filtro claro “updated since”.
Webhooks são o padrão melhor quando o tempo importa: “novo pedido recebido”, “pagamento falhou”, “ticket atribuído”. Eles reduzem chamadas de API desnecessárias e podem acionar trabalho na hora.
Uma regra prática é usar ambos quando a correção importa. Deixe webhooks darem velocidade e polling limpar o que você perdeu. Por exemplo, processe webhooks rapidamente e rode um poll agendado a cada 15 minutos (ou a cada poucas horas) para reconciliar lacunas causadas por eventos descartados ou outages temporários.
Um guia rápido:
- Se minutos de atraso são aceitáveis, comece com polling.
- Se atualizações precisam aparecer em segundos, comece com webhooks.
- Se o fornecedor é instável ou os eventos são críticos, planeje webhook + polling.
- Se a API tem limites pesados, prefira webhooks com polling leve.
- Se o volume de dados é alto, evite polls completos frequentes.
Antes de se comprometer, pergunte ao fornecedor algumas coisas e obtenha respostas claras:
- Quais tipos de evento existem, e eles são completos (create, update, delete)?
- Eles re-tentam webhooks, e por quanto tempo?
- É possível reproduzir eventos ou buscar um histórico por intervalo de tempo?
- Eles assinam requisições de webhook para que você possa verificar autenticidade?
- Eles suportam queries “updated since” para polling eficiente?
Passo a passo: desenhando uma sincronização que permanece correta
Uma sincronização “correta” não é só “os dados aparecem”. Significa que os registros certos batem, a mudança mais recente vence e você pode provar o que aconteceu quando algo der errado.
Comece com um plano que possa testar e monitorar:
- Defina a fonte da verdade e as regras. Escolha qual sistema é dono de cada campo. Por exemplo, o CRM é dono do nome do cliente, mas sua ferramenta de faturamento é dona do status da assinatura. Decida o que é “fresco o suficiente” (como “dentro de 5 minutos”) e quais erros são aceitáveis.
- Escolha identificadores estáveis. Armazene o ID único do terceiro junto ao seu ID interno. Evite usar email ou nome como chave (eles mudam). Se disponível, salve uma versão ou timestamp updated_at para detectar dados mais novos.
- Planeje importação inicial e depois updates incrementais. Trate a primeira importação como um job separado com checkpoints para poder retomar. Depois disso, processe apenas mudanças (eventos, queries “since” ou ambos) e registre um cursor como “last successful sync time”.
- Trate deletes e merges de forma explícita. Decida se deletes removem o registro, o arquivam ou marcam como inativo. Para merges, escolha qual ID sobrevive e mantenha trilha de auditoria.
- Defina sinais de monitoramento. Acompanhe lag de sincronização, chamadas falhadas e filas travadas. Alerta quando o lag ultrapassar seu limite, não apenas quando algo cair.
Ao implementar, mantenha as escolhas visíveis no seu modelo de dados: IDs externos, timestamps, campos de status e um lugar para armazenar checkpoints de sync. Essa estrutura é o que mantém a sincronização correta quando o mundo real fica bagunçado.
Idempotência e ordenação: o núcleo das integrações confiáveis
Se você construir integrações webhooks vs polling por tempo suficiente, uma regra aparece todo tempo: você verá duplicatas, retentativas e atualizações fora de ordem. Se sua sincronização não puder reprocessar a mesma mensagem com segurança, ela vai divergir com o tempo.
Idempotência significa “mesma entrada, mesmo resultado”, mesmo que chegue duas vezes. Trate cada evento recebido como “talvez repetido” e projete seu handler para ser seguro. Um padrão comum é: calcule uma chave de deduplicação, verifique se já processou e então aplique mudanças.
Chaves de deduplicação têm trade-offs. Um ID de evento é o ideal quando o provedor fornece um. Se não, você pode usar uma versão do objeto (como uma revisão incremental). Janelas de timestamp como “ignorar repetições por 10 minutos” são frágeis porque chegadas tardias acontecem.
Ordenação é a outra metade. Ordenação global é rara, então mire em ordenação por objeto. Aplique atualizações a um ticket, fatura ou cliente apenas se a versão for mais nova do que a que você salvou. Se não houver versão, use last-write-wins com regra clara (por exemplo, updated_at mais novo vence), e aceite que clock skew pode criar casos de borda.
Armazene o suficiente para recuperar e reproduzir sem adivinhar:
- Uma “última versão vista” por objeto ou updated_at
- Um cursor ou checkpoint do último processamento para jobs de polling
- Uma tabela de IDs de eventos processados (com regra de retenção se crescer rápido)
- O payload bruto por um curto período, para reexecutar correções
Exemplo: um webhook de pagamento do Stripe chega duas vezes, depois uma atualização “paid” chega antes do evento “created”. Se você armazenar a versão mais recente do status da fatura e ignorar atualizações mais antigas, o resultado ficará correto.
Padrões de retentativa e replay que evitam deriva silenciosa de dados
A maioria das integrações falha silenciosamente. Um webhook chega tarde, um job de polling bate no limite, ou seu app dá timeout enquanto salva. Sem retentativas e capacidade de replay, sistemas lentamente divergem até que um cliente reclame.
Retentativas de webhook: aceite rápido, processe com segurança
Provedores geralmente re-tentam quando você não retorna um código HTTP de sucesso com rapidez. Trate a requisição de webhook como uma notificação de entrega, não como o lugar para trabalho pesado.
Um padrão prático de webhook:
- Responda rápido com um 2xx após validação básica (assinatura, esquema, timestamp).
- Armazene o evento com um ID único e marque como pendente.
- Processe assincronamente com um worker e rastreie tentativas.
- Em erros temporários, retente mais tarde. Em erros permanentes, pare e alerte.
- Use 4xx para dados inválidos e 5xx apenas para problemas reais de servidor.
Isso evita a armadilha comum: pensar que “webhook recebido” significa “dados sincronizados”.
Retentativas em polling: seja educado com a API
Polling falha de modo diferente. O risco é uma manada de retries após uma breve queda, o que piora limites de taxa. Use backoff exponencial com jitter e mantenha um cursor “since” para não re-varrer tudo.
Quando não puder processar algo agora, coloque-o numa dead-letter queue (ou tabela) com a razão. Isso dá um lugar seguro para inspecionar, corrigir regras de mapeamento e re-executar sem adivinhar o que foi perdido.
Replay é como você cura falhas por missed events. Uma estratégia simples de replay:
- Escolha uma janela de tempo (por exemplo, últimas 24 horas) ou um conjunto de registros afetados.
- Rebusque o estado atual no provedor.
- Reaplique atualizações idempotentemente e corrija divergências.
- Registre o que mudou e por quê.
Exemplo: seu provedor de faturamento envia “invoice.paid”, mas seu banco ficou travado por 30 segundos. Você envia o evento para dead-letter e depois reprocessa buscando novamente a fatura e o status do pagamento, atualizando seus registros para bater.
Erros comuns e como evitá-los
A maioria dos bugs de sincronização não é um “grande problema de arquitetura”. São suposições pequenas que viram deriva silenciosa, registros duplicados ou atualizações perdidas.
Alguns que aparecem repetidamente:
- Fazer polling com muita frequência sem filtros incrementais. Rastreie um cursor (updated_at, event ID, token de página) e pergunte apenas por mudanças desde a última execução bem-sucedida.
- Tratar webhooks como entrega garantida. Mantenha um job de backfill que re-cheque o histórico recente (por exemplo, últimas 24–72 horas) e reconcilie o que faltou.
- Ignorar duplicatas. Faça cada escrita idempotente. Armazene o ID do evento do provedor (ou um ID externo estável) e recuse aplicar a mesma mudança duas vezes.
- Aceitar chamadas de webhook sem verificação. Valide o token de assinatura ou o método de verificação que o provedor oferece.
- Operar sem visibilidade da saúde da sync. Monitore lag, tamanho do backlog, último run bem-sucedido e taxas de erro. Alerta quando o lag ultrapassar um limite.
Muitos debates sobre “webhooks vs polling” perdem o ponto: a confiabilidade vem das proteções ao redor de qualquer método. Um webhook de pagamento pode chegar duas vezes ou atrasado. Se seu sistema cria registros diretamente a partir do webhook sem idempotência, você pode notificar ou cobrar um cliente duas vezes.
Checklist rápido para uma integração saudável
Checagens do dia a dia são similares independentemente de você usar webhooks, polling ou ambos. Você quer saber se os dados estão frescos, se erros estão se acumulando e se é possível recuperar de forma limpa.
Um checklist rápido que você pode rodar em alguns minutos:
- Atualidade: compare “último evento recebido” ou “último poll concluído” com o lag esperado.
- Falhas: procure retries em escalada ou jobs que não avançam. Combine contagem de erros com um timestamp de “último sucesso”.
- Cotas: verifique quantas chamadas de API usou e quanto resta. Se estiver perto do limite, reduza polling e agrupe requisições.
- Correção: confira somas entre sistemas (por exemplo, “pedidos hoje”) e amostre alguns registros recentes.
- Prontidão de recuperação: confirme que você pode reprocessar uma janela recente sem duplicatas ou perdas.
Um hábito útil é reproduzir periodicamente um período movimentado de forma controlada e confirmar que os resultados batem com a produção.
Exemplo: misturando webhooks e polling em um fluxo realista
Imagine um time de SaaS que precisa manter três sistemas em sincronia: um CRM (contatos e negócios), Stripe (cobranças e reembolsos) e uma ferramenta de suporte (status de tickets).
Eles usam uma abordagem webhook-first para tudo que precisa de reação rápida. Eventos do CRM atualizam o registro do cliente e disparam tarefas internas. Webhooks do Stripe criam faturas, liberam recursos após pagamento e marcam contas como inadimplentes em falhas de cobrança. Para a ferramenta de suporte, usam webhooks se disponíveis, mas mantêm um poll agendado porque estados de tickets podem mudar em massa.
Eles tratam polling como rede de segurança, não como motor principal. Toda noite, um job de reconciliação puxa as últimas 24 horas de mudanças nos sistemas e compara com o que o app armazenou.
Então ocorre um outage real: o endpoint de webhook fica fora por 20 minutos durante um deploy.
- CRM e Stripe re-tentam a entrega por algum tempo.
- Alguns eventos chegam atrasados, outros fora de ordem, e alguns podem expirar.
- O poll de reconciliação detecta uma lacuna (IDs de eventos faltando ou totais divergentes) e backfilla as mudanças perdidas.
O que eles registram: ID do evento recebido, timestamp do provedor, ID interno do registro e o resultado final (created, updated, ignored). O que dispara um alerta: falhas repetidas de webhook, pico de retries ou a reconciliação encontrando um número de updates perdidos acima de um pequeno limiar.
Próximos passos: implementar, monitorar e iterar
Um padrão prático para a maioria dos times é simples: use webhooks para imediatismo e mantenha um pequeno job de polling para reconciliação. Webhooks trazem mudanças rapidamente. Polling pega o que você perdeu por outages, assinaturas mal configuradas ou provedores que ocasionalmente descartam eventos.
Faça a sincronização correta antes de torná-la rápida. Trate cada mudança recebida como algo que pode ser aplicado mais de uma vez com segurança.
Três ações iniciais:
- Mapear eventos e campos do provedor para seu modelo interno, incluindo o que “delete”, “refund” ou “mudança de status” significam para você.
- Projetar idempotência desde o primeiro dia: armazene um ID de evento externo ou versão e faça cada atualização segura para reexecução sem criar duplicatas.
- Adicionar replay por propósito: mantenha um cursor “since last seen” ou polling por janelas de tempo e construa uma forma admin de reexecutar um intervalo quando algo estiver errado.
Quando estiver rodando, o monitoramento é o que mantém tudo funcionando. Acompanhe taxa de entrega de webhooks, falhas por motivo (timeouts, 4xx, 5xx) e o quanto sua poll de reconciliação está atrasada. Alerta tanto para “nenhum evento recebido” quanto para “muitos eventos recebidos”.
Se preferir construir isso sem escrever todo backend do zero, AppMaster é uma opção no-code que permite modelar dados, criar endpoints de webhook e projetar fluxos de retentativa/replay com ferramentas visuais, gerando código-fonte real para deploy.


