
Sesenta contenedores en un servidor
Un servidor bare-metal ejecuta decenas a cientos de contenedores Hoody. KSM y dedup BTRFS hacen que el costo marginal sea casi cero.
Stripe hace POST del cuerpo del evento a una ruta de pipe con ?n=12. Doce suscriptores hacen GET a la misma ruta con ?n=12. El pipe retiene el mensaje hasta que todos están conectados, y luego lo transmite a los doce a la vez. Sin broker, sin consumer group, sin DLQ.
Hoody Pipe es streaming HTTP con un modo multi-receptor. Añade ?n=N a las URLs del emisor y del receptor y el pipe espera hasta que se conecten N lectores, luego replica el cuerpo a todos ellos a la vez. Los lentos limitan su propia conexión — los rápidos siguen fluyendo.
Tu endpoint de Stripe reenvía el cuerpo del evento directo a /api/v1/pipe/billing?n=12. La conexión se bloquea mientras el pipe espera a que se reúnan los doce receptores.
Cada suscriptor es un bucle de curl en un contenedor, haciendo GET a la misma ruta con ?n=12. El pipe mantiene el cuerpo en memoria hasta que se conecta el duodécimo lector — sin cola en disco, nada que vaciar.
Una vez conectados todos, el cuerpo se transmite a los doce a la vez. Un lector lento aplica backpressure a su propio socket; los demás siguen. Cuando el último lector se desconecta, el pipe olvida el mensaje.
# 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.Misma URL, mismo query string, en ambos extremos. La conexión del emisor es el broker; las conexiones de los lectores son el consumer group. El backpressure es por socket, no por topic, porque no hay topic — hay un cuerpo en vuelo y doce sockets tirando de él.
Añadir un suscriptor es un curl más en un contenedor más. Quitar uno es matar el curl. No hay configuración de broker, ni rebalanceo de consumer group, ni DLQ que vaciar — la topología del cluster es simplemente lo que haya corriendo ahora mismo.
El pipe no rastrea quién está suscrito. Solo espera n conexiones por evento. Subes n en ambos extremos y el siguiente evento espera al nuevo aforo. No hay estado de membresía que corromper porque no hay membresía.
Cada línea de abajo es una categoría de trabajo que desaparece cuando el broker es el protocolo. Sin infraestructura que aprovisionar, sin abstracciones que aprender — solo curl y ?n.
Sin SQS, sin cluster Kafka, sin exchange RabbitMQ. El pipe es la cola, y vive un mensaje a la vez.
Sin offsets, sin commits, sin rebalanceos. El pipe retiene el cuerpo hasta que se conectan n sockets — ese es todo el modelo de coordinación.
Si el emisor se desconecta sin n lectores listos, el pipe expira (TTL de 5 min) y Stripe reintenta. Sin cubo de mensajes envenenados que cuidar.
Los suscriptores son bucles de curl. Los emisores son curl. El protocolo es HTTP. Cualquier cosa que pueda golpear una URL puede unirse al cluster.
Un lector lento limita su propia conexión. Los otros once siguen transmitiendo a velocidad máxima. No hay bloqueo de cabeza de línea en toda la flota.
El cuerpo desaparece en cuanto el último lector se desconecta. Sin política de retención que fijar, sin compactación de logs que programar, sin job de borrado bajo petición de GDPR que escribir.
Doce suscriptores, una URL, sin broker.
Los brokers de abajo son las cosas que solías instalar antes de que el fan-out HTTP fuera un parámetro de query. El lado derecho es lo que las reemplaza — una ruta, un n y doce procesos curl que no saben que son un cluster.
Doce receptores hacen GET a la misma ruta con el mismo n. El pipe es el broker — y olvida el mensaje en el segundo en que el último lector cuelga.
Si recurres a alguno de estos para difundir un webhook a N consumidores, el modelo del pipe está haciendo el mismo trabajo en dos invocaciones de curl — emisor en un lado, receptores en el otro.
El fan-out al que solías dedicar un sprint ahora es un parámetro de query. Añade ?n=12 y despliega.