Soixante conteneurs sur un seul serveur
Une seule machine bare-metal fait tourner des dizaines à des centaines de conteneurs Hoody. La déduplication KSM et BTRFS rend le coût marginal quasi nul.
Stripe POST le corps de l'évènement à un chemin pipe avec ?n=12. Douze subscribers font GET sur le même chemin avec ?n=12. Le pipe garde le message jusqu'à ce que tout le monde soit connecté, puis stream vers les douze d'un coup. Pas de broker, pas de consumer group, pas de DLQ.
Hoody Pipe, c'est du streaming HTTP avec un mode multi-récepteurs. Ajoutez ?n=N aux URLs émetteur et récepteur et le pipe attend que N lecteurs se branchent, puis duplique le corps vers eux tous en parallèle. Les lents throttle leur propre connexion — les rapides continuent à couler.
votre endpoint Stripe transmet le corps de l'évènement directement à /api/v1/pipe/billing?n=12. La connexion bloque pendant que le pipe attend que les douze récepteurs se rassemblent.
Chaque subscriber est une boucle curl dans un conteneur, qui fait GET sur le même chemin avec ?n=12. Le pipe garde le corps en mémoire jusqu'à ce que le douzième lecteur se connecte — pas de queue sur disque, rien à flush.
Une fois tout le monde connecté, le corps stream vers les douze d'un coup. Un lecteur lent applique du backpressure à son propre socket ; les autres continuent. Quand le dernier lecteur se déconnecte, le pipe oublie le message.
# Côté émetteur — votre handler de webhook Stripe.
# Le pipe garde le corps jusqu'à ce que 12 lecteurs soient branchés.
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"
# Côté récepteur — un des douze conteneurs subscriber.
# Même chemin, même n. Stream le corps de l'évènement quand le fan-out est prêt.
curl -N "https://api.hoody.com/api/v1/pipe/billing?n=12" \
-H "Authorization: Bearer $HOODY_TOKEN" | ./billing-handler.sh
# n doit matcher des deux côtés — un mismatch retourne 400.
# Par défaut n=1 est point-à-point. n=12 est du fan-out pour douze.Même URL, même query string, des deux côtés. La connexion de l'émetteur est le broker ; les connexions des lecteurs sont le consumer group. Le backpressure est par socket, pas par topic, parce qu'il n'y a pas de topic — il y a un corps en vol et douze sockets qui tirent dessus.
Ajouter un subscriber, c'est un curl de plus dans un conteneur de plus. Le retirer, c'est tuer le curl. Pas de config broker, pas de rebalancing de consumer-group, pas de DLQ à drainer — la topologie du cluster est juste l'ensemble des process qui se trouvent à tourner maintenant.
Le pipe ne suit pas qui est subscribed. Il attend juste n connexions par évènement. Augmente n des deux côtés et le prochain évènement attend le nouvel effectif. Il n'y a pas d'état de membership à corrompre parce qu'il n'y a pas de membership.
Chaque ligne ci-dessous est une catégorie de boulot qui disparaît quand le broker est le protocole. Pas d'infra à provisionner, pas d'abstractions à apprendre — juste curl et ?n.
Pas de SQS, pas de cluster Kafka, pas d'exchange RabbitMQ. Le pipe est la queue, et il vit pour un message à la fois.
Pas d'offsets, pas de commits, pas de rebalances. Le pipe garde le corps jusqu'à ce que n sockets se branchent — c'est tout le modèle de coordination.
Si l'émetteur se déconnecte sans n lecteurs prêts, le pipe time out (TTL 5 min) et Stripe retry. Pas de seau à messages empoisonnés à surveiller.
Les subscribers sont des boucles curl. Les émetteurs sont curl. Le protocole est HTTP. Tout ce qui peut taper une URL peut rejoindre le cluster.
Un lecteur lent throttle sa propre connexion. Les onze autres continuent à streamer à pleine vitesse. Pas de head-of-line blocking sur la flotte.
Le corps disparaît au moment où le dernier lecteur se déconnecte. Pas de politique de rétention à régler, pas de log-compaction à planifier, pas de job RGPD delete-on-request à écrire.
Douze subscribers, une URL, pas de broker.
Les brokers ci-dessous, ce sont les choses que vous installiez avant que le fan-out HTTP ne devienne un paramètre de query. La colonne de droite, c'est ce qui les remplace — un chemin, un n, et douze process curl qui ne savent pas qu'ils sont un cluster.
Douze récepteurs font GET sur le même chemin avec le même n. Le pipe est le broker — et oublie le message la seconde où le dernier lecteur raccroche.
Si vous attrapez l'un de ces outils pour broadcaster un webhook à N consommateurs, le modèle pipe fait le même boulot en deux invocations curl — émetteur d'un côté, récepteurs de l'autre.
Le fan-out pour lequel vous écriviez un sprint est désormais un paramètre de query. Ajoutez ?n=12 et livrez.