Webhooks (Assíncronos)
Padrão arquitetural de interação assíncrona entre serviços (Event-driven Push), no qual o provedor de eventos envia uma requisição HTTP POST com dados para a URL registrada do consumidor quando ocorre um evento sistêmico.
1. Visão Geral da Conceção e o Problema Sistémico
A integração tradicional de sistemas via polling constante (Polling / Short Polling) sofre de dois problemas mutuamente exclusivos:
- Alta latência de resposta: Se o cliente verifica alterações a cada 60 segundos, os dados são entregues com um atraso médio de 30 segundos.
- Desperdício colossal de recursos computacionais: 99% das requisições HTTP retornam respostas vazias
304 Not Modifiedou[], sobrecarregando o banco de dados e a stack de rede.
Webhooks (Chamadas de retorno via HTTP) mudam o paradigma de Pull para Push. Em vez de perguntar: "Há novos dados?", o consumidor registra sua URL (Webhook Listener). Assim que um evento ocorre no sistema do provedor (transação Stripe bem-sucedida, novo commit no GitHub, mensagem recebida no Telegram), o provedor envia uma requisição HTTP POST com payload JSON diretamente para o servidor do assinante.
Polling Tradicional (Desperdício de Recursos):
Cliente ---> GET /events?since=... ---> Servidor (Vazio: [])
Cliente ---> GET /events?since=... ---> Servidor (Vazio: [])
Cliente ---> GET /events?since=... ---> Servidor (Novo evento!)
Webhook Orientado a Eventos (Push Instantâneo):
Provedor de eventos (Stripe / GitHub / Telegram)
|
| Evento: charge.succeeded (Payload do Evento + Assinatura HMAC)
| HTTP POST https://api.mysite.com/webhooks/stripe
v
Consumidor (Validação da assinatura -> 200 OK -> Fila em segundo plano RabbitMQ/Redis)
2. Taxonomia Arquitetural e Modelo Mental
O ciclo de vida de um webhook apoia-se em três pilares arquiteturais:
- Autenticação Criptográfica (Assinatura HMAC):
- O provedor gera um hash criptográfico do corpo da requisição (
raw body) usando uma chave secreta compartilhada (Webhook Secret), adicionando-o ao cabeçalho (por exemplo,Stripe-SignatureouX-Hub-Signature-256). - O consumidor calcula o mesmo hash e valida-o, eliminando o risco de falsificação de requisições por atacantes.
- O provedor gera um hash criptográfico do corpo da requisição (
- Idempotência e Deduplicação (Motor de Idempotência):
- Cada evento possui um ID globalmente único (
evt_xxxxxxxxxx). - O consumidor verifica atomicamente a existência do ID no cache/BD (por exemplo, via
INSERT ... ON CONFLICT DO NOTHINGou RedisSET key NX EX 86400).
- Cada evento possui um ID globalmente único (
- Política de Entrega Garantida e Retentativas (Retry & Dead-Letter Queue):
- Em caso de indisponibilidade do servidor do consumidor, o provedor repete as requisições seguindo uma escala exponencial (Exponential Backoff com jitter): após 5 min, 30 min, 2 horas, 12 horas.
- Eventos que não puderam ser processados após o número máximo de tentativas são direcionados para a Dead-Letter Queue (DLQ) para análise manual pelos engenheiros.
3. Pipeline Técnico e Mecânica Interna
Processador de Produção com Verificação HMAC (Node.js / Express / TypeScript)
[!IMPORTANT] Para verificar a assinatura, é necessário obter o corpo bruto da requisição (
raw buffer), e não o objeto parseadoreq.body; caso contrário, o hash não coincidirá devido a divergências nos espaços em branco e na ordenação das chaves JSON.
import express, { Request, Response } from "express";
import crypto from "crypto";
const app = express();
// Отримання raw buffer для ендпоінтів вебхуків
app.post(
"/api/v1/stripe-webhook",
express.raw({ type: "application/json" }),
async (req: Request, res: Response) => {
const signature = req.headers["stripe-signature"] as string;
const secret = process.env.STRIPE_WEBHOOK_SECRET!;
if (!signature) {
return res.status(400).send("Missing signature header");
}
// 1. Криптографічна валідація підпису через HMAC SHA-256
const computedHmac = crypto
.createHmac("sha256", secret)
.update(req.body)
.digest("hex");
// Безпечне порівняння за фіксований час
const isValid = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(computedHmac)
);
if (!isValid) {
return res.status(401).send("Invalid signature");
}
const payload = JSON.parse(req.body.toString());
const eventId = payload.id;
// 2. Ідемпотентна перевірка дедуплікації
const isNew = await redis.set(`webhook:processed:${eventId}`, "1", "NX", "EX", 86400);
if (!isNew) {
// Подію вже оброблено — повертаємо 200 OK без повторного виконання
return res.status(200).json({ status: "already_processed" });
}
// 3. Відправка важкої роботи в чергу BullMQ
await eventQueue.add("process_payment", payload);
// 4. Миттєве підтвердження отримання
return res.status(200).json({ received: true });
}
);
4. Cenários de Engenharia Prática em Produção
01. Gateway de Pagamento para AI SaaS (Stripe / Paddle / LiqPay)
O usuário paga a assinatura do plano Pro. O sistema de pagamento gera o evento invoice.payment_succeeded. O webhook atualiza instantaneamente o status do usuário no banco de dados, reseta os limites de tokens no Redis e envia um e-mail de boas-vindas, permitindo que o usuário continue trabalhando sem recarregar a página.
02. Gatilho de Pipeline Autônomo de CI/CD (GitHub Webhooks)
Um engenheiro executa git push na branch main. O GitHub envia um payload com o hash do commit para o próprio servidor Coolify ou ArgoCD. O servidor verifica o segredo, clona o código alterado, executa testes unitários em um container Docker isolado e atualiza o serviço de produção utilizando a estratégia Blue/Green.
03. Coleta Assíncrona de Resultados de Inferência de Modelos de IA Pesados
Ao chamar modelos de geração de vídeo (Runway, Kling) ou treinamento de LoRA, a requisição pode levar vários minutos. Em vez de manter uma conexão HTTP aberta, o cliente transmite o webhook_url. Assim que o cluster GPU conclui a geração, ele envia um webhook com o link final do S3 para a mídia gerada.
5. Armadilhas, Erros Comuns e Segurança
- Parsing de JSON antes da verificação da assinatura:
Se o middleware padrão
express.json()for executado antes da verificação da assinatura, o serializador pode alterar a ordem dos campos, o escape de caracteres Unicode ou o formato dos números, resultando em incompatibilidade do checksum HMAC e rejeição com erroInvalid Signature. - Bloqueio Síncrono de Execução (Deadlock de Webhook):
A execução de transações pesadas ou requisições HTTP longas a APIs externas dentro do handler do webhook garantidamente causará timeout no lado do provedor. Retorne
200 OKimediatamente após a validação da assinatura e o enfileiramento da tarefa. - Ausência de Validação de Timestamps (Ataques de Replay): Um atacante que interceptou uma requisição de webhook legítima e assinada pode reenviá-la uma hora depois. Os provedores incluem um timestamp na assinatura. Verifique se a diferença entre o tempo da requisição e o relógio do sistema do servidor não excede a janela permitida (por exemplo, 5 minutos).
FAQ: Webhooks (Assíncronos)
Termos relacionados
Telegram Bot API
Interface HTTP oficial da plataforma Telegram, que permite criar chatbots autônomos, assistentes de IA, interfaces do Telegram Mini Apps (TMA) e canais de notificação interativa.
Cron Schedulers & Systemd Timers
System daemons (Linux cron, systemd timers) and distributed queues (BullMQ, Temporal) that ensure the guaranteed execution of periodic engineering tasks, backups, data synchronization, and AI agents according to schedule.
Rate Limiting (Limitação de Frequência de Requisições e Proteção de API)
Mecanismo sistêmico de controle da intensidade do tráfego de entrada e saída (Token Bucket, Sliding Window) para proteger o backend contra esgotamento de recursos, ataques de força bruta, DDoS na camada 7 e estouro financeiro em endpoints de IA.
Proxy reverso (Nginx, Caddy, Traefik)
Camada de arquitetura de servidor intermediária que recebe tráfego externo da internet (portas 80/443), realiza a terminação SSL/TLS, compressão (Brotli/Gzip), cache de arquivos estáticos e roteia com segurança as requisições para aplicações internas.