Arquitetura3 de agosto de 20268 min de leitura

Webhooks vs polling: decida pelo modo de falha, não por moda

O polling desperdiça requisições, mas se recupera. Webhooks são eficientes, mas falham em silêncio. E o híbrido que a maioria das integrações sérias monta.

POLLING · A LACUNA SE FECHA SOZINHAseu loopfora do ar 3 hpróximo pollsince=cursorem diaa recuperação não exige nenhum código que você ainda não tenha escritoWEBHOOKS · A LACUNA É INVISÍVELprovedor500s 3 htenta e desistenadasem erro, sem cursornenhum sinalem lugar nenhumausência de dados parece exatamente ausência de atividade
A comparação que importa não é de requisições por hora. É o que cada modelo deixa para trás quando quebra.

Costuma-se dizer que o polling é a abordagem ingênua e que webhooks são o próximo nível. É uma história bem amarrada, e ela leva equipes à arquitetura errada com uma frequência surpreendente.

A pergunta útil não é qual dos dois é mais eficiente. São os webhooks, e com folga. A pergunta útil é o que cada um faz quando quebra, porque é com essa propriedade que você vai conviver às 3h da manhã, e os dois são quase exatamente opostos.

TL;DR

  • O polling falha de forma ruidosa e recuperável: você percebe, e a próxima consulta recupera o atraso
  • Webhooks falham em silêncio e de forma permanente: nada dá erro, o evento simplesmente some
  • Webhooks obrigam você a construir a infraestrutura que o polling dá de graça: novas tentativas (retries), deduplicação, ordem e verificação de assinatura
  • A maioria das integrações em produção acaba híbrida: webhooks para a latência, um polling de conciliação para a corretude
  • Se você só puder construir um, e a corretude importar mais que a latência, faça polling

A comparação que costuma aparecer

PollingWebhooks
LatênciaSeu intervalo, metade dele em médiaQuase em tempo real
Requisições desperdiçadasA maioriaNenhuma
Quem paga o custoVocêO remetente
Exige endpoint públicoNãoSim
OrdemVocê controlaNão garantida
ConfiguraçãoUma chamada HTTP e um loopEndpoint, TLS, verificação de assinatura, deduplicação, novas tentativas

Leia essa tabela e os webhooks ganham nas linhas que as pessoas costumam otimizar. É por isso que tantas equipes trocam, colocam em produção e depois perdem eventos em silêncio por dois meses.

A comparação que de fato decide

Pergunte, em vez disso: quando isso quebrar, como eu vou ficar sabendo?

O polling degrada de formas que se anunciam. Seu servidor está fora do ar, então o loop não roda. Quando ele volta, a próxima consulta pergunta "o que mudou desde o meu último cursor" e recebe tudo. A recuperação é automática e não exige nenhum código que você ainda não tenha escrito. Se a API está fora do ar, sua consulta recebe um 500 e você vê isso na hora na sua própria taxa de erros. No modelo pull, você sempre sabe qual foi sua última posição boa conhecida, e só essa propriedade já vale muito.

Webhooks falham de formas invisíveis do seu lado. Seu endpoint responde 500 por seis horas durante um deploy ruim. O provedor tenta de novo, desiste e segue em frente. Seus logs não mostram nada de anormal, porque você não consegue registrar uma requisição que nunca recebeu. Não existe cursor, nem detector de lacunas, nem um número "estou 400 eventos atrasado" em lugar nenhum do seu sistema. Ausência de dados parece idêntica a ausência de atividade, e num domingo tranquilo você não consegue diferenciar uma da outra.

POLLING · A LACUNA SE FECHA SOZINHAseu loopfora do ar 3 hpróximo pollsince=cursorem diaa recuperação não exige nenhum código que você ainda não tenha escritoWEBHOOKS · A LACUNA É INVISÍVELprovedor500s 3 htenta e desistenadasem erro, sem cursornenhum sinalem lugar nenhumausência de dados parece exatamente ausência de atividade

Essa assimetria deveria decidir a questão. O pior caso do polling são dados desatualizados que você vai recuperar. O pior caso dos webhooks são dados ausentes que você nunca vai saber que faltaram.

Os custos de segunda ordem vêm daí. Com webhooks, a lógica de novas tentativas passa a ser sua, porque a janela do provedor é finita e até os provedores generosos desistem depois de três dias. A idempotência é sua, porque a entrega pelo menos uma vez (at-least-once) torna as duplicatas uma garantia. As proteções de ordem são suas, porque as novas tentativas deixam o evento #2 passar na frente do evento #1. A verificação de assinatura é sua, porque seu endpoint é público e qualquer um pode fazer POST nele. E também é seu um endpoint HTTPS público que fica sempre no ar, o que é um requisito de disponibilidade diferente de "nosso app costuma estar no ar".

Nenhum deles é difícil sozinho. Juntos, eles são o motivo pelo qual "é só usar webhooks" vira um projeto de duas semanas que não está pronto quando você acha que está.

Quando o polling é de fato a resposta certa

Não deixe o argumento da eficiência convencer você do contrário nestes casos.

O óbvio é a latência de que você não precisa. Uma sincronização contábil noturna, uma conciliação de estoque, uma rotina de enriquecimento de CRM: se ninguém percebe um atraso de 5 minutos, você está pagando complexidade real por uma propriedade que não tem valor para ninguém.

Depois, há o caso de não ter onde receber. Apps desktop, ferramentas internas atrás de uma VPN, uma tarefa rodando no notebook de alguém. Abrir um túnel até o localhost para receber um webhook é uma técnica de desenvolvimento, não uma arquitetura de produção, e escrevemos sobre onde fica essa fronteira em Por que o ngrok não basta.

O caso em que as equipes mais erram é quando a corretude importa mais que a latência e o prazo é daqui a uma semana. Um polling com cursor, que você consegue entender, ganha de um pipeline de webhooks feito pela metade.

Volume baixo pesa para o mesmo lado. Uma consulta a cada 5 minutos dá 288 requisições por dia, algo que nenhum rate limit percebe, e a simplicidade operacional vem de graça. O mesmo vale para um provedor cujos próprios webhooks são instáveis: se a entrega dele não é confiável e o log de eventos é raso, fazer polling na API dele é mais confiável do que confiar no envio dele.

Quando os webhooks justificam a complexidade

Webhooks se pagam quando há uma pessoa esperando. Confirmação de pagamento, status de deploy, uma mensagem de chat. Uma latência abaixo de um segundo faz diferença, e fazer polling rápido o bastante para imitar isso significa martelar uma API.

Eles também ganham quando os eventos são raros e imprevisíveis. Fazer polling de algo que acontece duas vezes por dia significa que cerca de 99,9% das suas requisições voltam vazias, e é para esse caso que os webhooks foram projetados. No outro extremo, o volume pode tornar o polling inviável de vez: dez mil lojas, cada uma precisando de dados com no máximo 30 segundos de atraso, dão 28,8 milhões de requisições por dia, e você vai bater nos rate limits muito antes de chegar lá.

O último caso são tarefas longas. Transcodificação de vídeo, inferência de modelo, exportação em lote. O provedor sabe quando terminou e você estaria chutando, e é por isso que as APIs de IA e de mídia empurram tanto os webhooks. Veja Webhooks para agentes de IA.

O híbrido, que é o que você vai construir de qualquer jeito

Quase toda integração madura acaba aqui, e chegar de propósito sai mais barato do que chegar depois de um incidente. Os webhooks cuidam da latência; um polling periódico de conciliação cuida da corretude.

// Fast path: webhook, near-real-time
export async function POST(req: Request) {
  const event = await verify(req);
  await upsertEvent(event);           // idempotent by provider event id
  return new Response(null, { status: 200 });
}

// Safety net: every 15 minutes, ask what we should have
async function reconcile() {
  const now = new Date();             // before listing, so nothing updated mid-sweep is skipped
  const since = await getLastReconciledAt();
  for await (const obj of provider.list({ updated_since: since })) {
    await upsertEvent(obj);           // same idempotent path, no-op if webhook won
  }
  await setLastReconciledAt(now);
}

A rotina de conciliação custa uma função agendada e reaproveita o código que você já escreveu. Em troca, ela converte a pior propriedade dos webhooks, a perda silenciosa e permanente, em "até 15 minutos de atraso". É um risco completamente diferente. O pior caso nem é um pagamento perdido, que alguém acaba percebendo, mas um access.revoked perdido, que ninguém percebe.

O requisito que faz isso funcionar é que os dois caminhos passem pela mesma função de escrita idempotente. Se o webhook já tratou o evento, a conciliação não faz nada. Se não tratou, a conciliação corrige. Isso só vale se você deduplicar pelo ID de evento do provedor, e não pelo seu próprio horário de chegada. Os padrões estão em Você recebeu o mesmo webhook duas vezes.

Depois, instrumente a sobreposição. Conte quantas vezes a conciliação encontra algo que o webhook perdeu. Esse número é a taxa real de perda do seu pipeline de webhooks, e é a única medida honesta dela que você vai ter. Se ficar em zero por um mês, seus webhooks estão saudáveis. Se disparar, você tem uma queda que, de outro jeito, nunca teria detectado.

O meio-termo que as pessoas esquecem

O polling não precisa ser burro.

O polling com cursor, ou seja, ?since=<cursor> em vez de "buscar tudo e comparar", é drasticamente mais barato e nunca pula um item, porque o cursor só avança quando o processamento dá certo.

Requisições condicionais, If-None-Match com ETags ou If-Modified-Since, recebem um 304 sem corpo. Muitos provedores não contam essas requisições no seu rate limit. Dá para fazer polling agressivo gastando muito pouco.

O long polling dá uma latência parecida com a dos webhooks, com a recuperação do modelo pull. É mais raro, mas, onde existe, costuma ser o melhor dos dois mundos.

Se você descartou o polling por causa do custo de buscar tudo em intervalos fixos, talvez estivesse comparando com a pior versão dele.

Onde o AnyHook entra

Os webhooks falham em silêncio porque ninguém guarda um registro do que deveria ter chegado. O AnyHook é esse registro.

Os provedores fazem POST para in.anyhook.net/you/app. O AnyHook grava cada evento antes de tentar a entrega, então:

  • A lacuna fica visível. O AnyHook conta as falhas de entrega, mostra cada uma e envia alertas com 1, 5 e 20 falhas consecutivas, e "silencioso" deixa de ser verdade
  • A recuperação vira um replay (um novo envio de um evento armazenado, feito por você), e não uma rotina de conciliação. Selecione o período em que seu servidor ficou fora do ar e entregue de novo a partir do log. Replays de eventos com falha não consomem sua cota mensal, embora tenham um limite diário e usem sua franquia de computação
  • Pagamos o imposto da infraestrutura uma vez só, do nosso lado: novas tentativas com backoff exponencial, um log durável e um único cabeçalho AnyHook-Signature em vez de um esquema de verificação por provedor

Isso não elimina o argumento a favor de um polling de conciliação. Se um provedor nunca enviou o evento, nenhum relay de webhooks (um serviço que recebe, guarda e encaminha seus webhooks) consegue inventá-lo. Mas reduz o modo de falha de "silencioso e permanente" para "registrado, com alerta e disponível para replay", que é a maior parte do que o híbrido estava comprando para você.

Para ver isso antes de se cadastrar em qualquer coisa, um único comando retorna uma URL de entrada ativa, sem conta:

curl -X POST https://anyhook.net/api/v1/quickstart

A resposta traz o campo inbound_url, para apontar um provedor, o campo api_key, para ler o log de eventos pela API, e o campo claim_url. O endpoint é temporário: o AnyHook exclui o endpoint e os eventos dele depois de 7 dias, a menos que você abra a URL de vinculação e entre na sua conta, o que mantém a mesma URL.

Conclusão

Escolha pelo modo de falha. O polling atrasa, mas se recupera sozinho; os webhooks são rápidos, mas perdem coisas em silêncio. Se a latência não afeta uma pessoa nem um rate limit, o polling não é a opção de iniciante, é a que tem o melhor pior caso. E, se você usa webhooks em produção, adicione o polling de conciliação antes de precisar dele, porque a métrica que ele produz é o único jeito de saber quantos eventos você está perdendo de fato.

Todos os posts3 de agosto de 2026 · 8 min

Pare de perder webhooks.

Troque uma URL. Tenha novas tentativas, um log de eventos e replay com um clique. Ou veja antes: crie uma conta, rode a simulação de queda de 30 segundos e veja um evento sobreviver ao seu servidor fora do ar. Não precisa de servidor.