
Sessenta contêineres em um servidor
Uma caixa bare-metal executa dezenas a centenas de contêineres Hoody. KSM e BTRFS dedup fazem o custo marginal próximo a zero.
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.
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.
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.
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.
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.
# 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.
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.
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.
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 SQS, sem cluster Kafka, sem exchange RabbitMQ. O pipe é a fila, e ele vive por uma mensagem de cada vez.
Sem offsets, sem commits, sem rebalances. O pipe segura o corpo até n sockets se conectarem — esse é o modelo de coordenação inteiro.
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.
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.
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.
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.
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.
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.
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.
O fan-out que você usaria uma sprint para escrever virou um query parameter. Anexe ?n=12 e suba.