Cover do episódio 81: O que é webhook e por que é muito melhor do que polling
#0813 de junho, 20193 min leituraTecnologia sem HypeS3 · 2018–2019

O que é webhook e por que é muito melhor do que polling

Polling parece óbvio quando você começa. Funciona. Até você entender webhook e perceber que estava resolvendo o problema do jeito mais caro possível.

WebhookAPIIntegraçãoBackend

Minha primeira integração com pagamento fazia polling.

A cada 5 segundos, meu sistema perguntava ao gateway: "esse pagamento foi aprovado?" O gateway respondia "não" — novamente — e eu esperava mais 5 segundos.

Funcionava. Era o jeito mais ineficiente possível de resolver o problema, mas funcionava.

Quando aprendi sobre webhook, me perguntei por que não tinha pensado nisso antes.


Polling: o que é e por que parece intuitivo

Polling é perguntar repetidamente até ter resposta.

while True:
    status = verificar_pagamento(pagamento_id)
    if status == 'aprovado':
        processar_pedido()
        break
    time.sleep(5)

Intuitivo porque segue o modelo mental de "fico esperando até saber". É como você verifica se o ônibus chegou olhando pela janela a cada 5 minutos.

O problema: para cada pagamento em andamento, você faz uma requisição a cada 5 segundos. 100 pagamentos simultâneos = 20 requisições por segundo. Você está batendo na API do gateway 20 vezes por segundo para ouvir "não" 19 vezes e "sim" uma.

Isso tem custo. A maioria das APIs tem rate limit. E você está usando toda essa capacidade para ouvir "ainda não".


Webhook: o modelo inverso

Webhook inverte a lógica. Em vez de você perguntar, o sistema externo te avisa quando algo acontece.

Você registra uma URL no gateway: "quando um pagamento mudar de status, manda um POST para https://meusite.com/webhooks/pagamento".

Quando o pagamento é aprovado, o gateway faz uma requisição HTTP para sua URL com os dados do evento. Você processa, responde 200, pronto.

Zero polling. Zero "ainda não". Você recebe exatamente quando o evento acontece.


Como implementar o lado receptor

@app.route('/webhooks/pagamento', methods=['POST'])
def receber_webhook():
    # 1. valida assinatura (importante!)
    signature = request.headers.get('X-Webhook-Signature')
    if not validar_assinatura(request.data, signature, WEBHOOK_SECRET):
        return '', 401
    
    # 2. parseia o evento
    evento = request.json
    
    if evento['tipo'] == 'pagamento.aprovado':
        processar_pedido(evento['pagamento_id'])
    elif evento['tipo'] == 'pagamento.recusado':
        notificar_usuario(evento['pagamento_id'])
    
    # 3. responde 200 RÁPIDO
    return '', 200

Três regras que aprendi na prática: valida a assinatura (qualquer pessoa pode fazer POST para sua URL — o gateway envia uma assinatura HMAC do payload, valida antes de processar), responde 200 rápido (o gateway tem timeout — aceita o evento, coloca numa fila, processa assincronamente, responde 200 imediatamente), e trata duplicatas (gateways enviam webhook mais de uma vez se não recebem 200 a tempo — seu handler precisa ser idempotente).


Quando polling ainda faz sentido

Nem sempre webhook é possível.

Se o sistema externo não suporta webhook — e tem muitos sistemas legados que não suportam — polling é a única opção.

Se você precisa de estado em tempo real contínuo (dashboards de métricas, por exemplo), polling ou websocket fazem mais sentido do que webhook.

Se você está em ambiente local de desenvolvimento, receber webhook de sistema externo exige tunnel (ngrok, por exemplo) porque seu localhost não é acessível da internet.

Mas quando o sistema externo suporta webhook e o evento é assíncrono por natureza (pagamento aprovado, email entregue, build concluído), webhook é sempre a escolha certa.


O modelo mental que fica

Polling = você busca a informação.
Webhook = a informação te encontra.

Para qualquer integração nova, primeiro pergunta: esse sistema suporta webhook? Se sim, usa. Se não, polling com intervalo inteligente (exponential backoff, não intervalo fixo).

Essa semana: olha as integrações do seu projeto atual. Tem alguma usando polling que poderia usar webhook? Vale verificar se o sistema externo suporta — economiza requisições, reduz latência, simplifica o código.