Pular para o conteúdo
use-cases / the-webhook-fan-out-you-didnt-have-to-build / hero
PIPE · HTTP FAN-OUT

O fan-out de webhook que você não precisou construir

O Stripe faz POST do corpo do evento para um caminho de pipe com ?n=12. Doze assinantes fazem GET no mesmo caminho com ?n=12. O pipe segura a mensagem até todos estarem conectados, depois transmite aos doze de uma vez. Sem broker, sem consumer group, sem DLQ.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / mechanism

Uma URL. Doze leitores. Backpressure por conexão.

O Hoody Pipe é streaming HTTP com modo multi-receiver. Anexe ?n=N tanto na URL do sender quanto na do receiver e o pipe espera até N leitores se conectarem, depois espelha o corpo para todos simultaneamente. Os lentos limitam a própria conexão — os rápidos seguem fluindo.

01PASSO 01 · INTAKE

O Stripe faz POST no pipe

Seu endpoint do Stripe encaminha o corpo do evento direto para /api/v1/pipe/billing?n=12. A conexão bloqueia enquanto o pipe espera os doze receivers se reunirem.

02PASSO 02 · MONTAGEM

Doze assinantes se conectam

Cada assinante é um loop curl em um contêiner, fazendo GET no mesmo caminho com ?n=12. O pipe segura o corpo em memória até o décimo segundo leitor conectar — sem fila em disco, nada para flushar.

03PASSO 03 · STREAM

Fan-out, depois esqueça

Quando todos estão conectados, o corpo flui para os doze de uma vez. Um leitor lento aplica backpressure no próprio socket; os outros seguem em frente. Quando o último leitor desconecta, o pipe esquece a mensagem.

stripe-webhook.sh
# Sender side — your Stripe webhook handler.
# Pipe holds the body until 12 readers are attached.
curl -X POST "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary "@stripe-event.json"

# Receiver side — one of twelve subscriber containers.
# Same path, same n. Streams the event body when fan-out is ready.
curl -N "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" | ./billing-handler.sh

# n must match on both ends — mismatch returns 400.
# Default n=1 is point-to-point. n=12 is fan-out for twelve.

Mesma URL, mesma query string, nas duas pontas. A conexão do sender é o broker; as conexões dos leitores são o consumer group. O backpressure é por socket, não por tópico, porque não existe tópico — existe um corpo em trânsito e doze sockets puxando.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / fleet

Assinantes vão e vêm como processos

Adicionar um assinante é mais um curl em mais um contêiner. Remover é matar o curl. Não tem config de broker, sem rebalanceamento de consumer-group, sem DLQ para drenar — a topologia do cluster é simplesmente os processos que estão rodando agora.

diff de assinantes · últimos 5 minutossem rebalanceamento necessário
  • + ADICIONADO
    WHKAUD
    dois novos contêineres subiram
  • − REMOVIDO
    MIX
    contêiner morto, curl saiu
  • = ESTÁVEL
    BILANLLOGFRDSUCSLACRMCDNNOT
    ainda no mesmo caminho com n=12

O pipe não rastreia quem está inscrito. Ele só espera n conexões por evento. Aumente n nas duas pontas e o próximo evento espera o novo total. Não tem estado de membresia para corromper porque não existe membresia.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / advantages

O que você não precisa mais operar

Cada linha abaixo é uma categoria de trabalho que desaparece quando o broker é o protocolo. Sem infraestrutura para provisionar, sem abstrações para aprender — só curl e ?n.

  • Sem fila para provisionar

    Sem SQS, sem cluster Kafka, sem exchange RabbitMQ. O pipe é a fila, e ele vive por uma mensagem de cada vez.

  • Sem contabilidade de consumer-group

    Sem offsets, sem commits, sem rebalances. O pipe segura o corpo até n sockets se conectarem — esse é o modelo de coordenação inteiro.

  • Sem DLQ para drenar

    Se o sender desconecta sem n leitores prontos, o pipe expira (TTL de 5 min) e o Stripe tenta de novo. Sem balde de mensagens venenosas para vigiar.

  • Sem SDK por linguagem

    Os assinantes são loops curl. Os senders são curl. O protocolo é HTTP. Qualquer coisa que consegue acertar uma URL pode entrar no cluster.

  • Backpressure por socket

    Um leitor lento limita a própria conexão. Os outros onze seguem fluindo à velocidade total. Não existe head-of-line blocking pela frota.

  • Esquecível por padrão

    O corpo some no momento em que o último leitor desconecta. Sem política de retenção para configurar, sem log-compaction para agendar, sem job de delete-on-request por GDPR para escrever.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / punchline

Doze assinantes, uma URL, sem broker.

Os brokers abaixo são as coisas que você instalava antes de o fan-out HTTP virar um query parameter. O lado direito é o que os substitui — um caminho, um n e doze processos curl que não sabem que são um cluster.

O QUE VOCÊ NÃO RODA
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • Exchanges RabbitMQ
  • Roteadores de webhook customizados
O QUE VOCÊ CHAMA NO LUGAR
POST /api/v1/pipe/billing?n=12

Doze receivers fazem GET no mesmo caminho com o mesmo n. O pipe é o broker — e esquece a mensagem no segundo em que o último leitor desliga.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / replaces

O que isso substitui

Se você recorre a qualquer um destes para transmitir um webhook a N consumidores, o modelo do pipe faz o mesmo trabalho em duas invocações curl — sender de um lado, receivers do outro.

  • AWS Lambda + SQS/SNSBroker por tópico, IAM por assinante
  • Apache KafkaCluster, ZooKeeper/KRaft, consumer groups
  • Exchanges RabbitMQBindings, vhosts, UI de gerência por env
  • Roteadores de webhook customizadosServiço para manter, retries para inventar
  • Serviços de Pub/SubCobrança por mensagem, lock-in com GCP/AWS
  • Plugins de fan-out HTTPPlugin de gateway por stack, sem backpressure
use-cases / the-webhook-fan-out-you-didnt-have-to-build / cta

O fan-out que você usaria uma sprint para escrever virou um query parameter. Anexe ?n=12 e suba.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / related

Leia os outros