Aller au contenu
use-cases / the-webhook-fan-out-you-didnt-have-to-build / hero
PIPE · FAN-OUT HTTP

Le fan-out de webhook que vous n'avez pas eu à construire

Stripe POST le corps de l'événement vers un chemin de pipe avec ?n=12. Douze abonnés font GET sur le même chemin avec ?n=12. Le pipe retient le message jusqu'à ce que tout le monde soit connecté, puis diffuse aux douze à la fois. Pas de broker, pas de consumer group, pas de DLQ.

Lire la doc pipe
use-cases / the-webhook-fan-out-you-didnt-have-to-build / mechanism

Une URL. Douze lecteurs. Backpressure par connexion.

Hoody Pipe, c'est du streaming HTTP avec un mode multi-récepteurs. Ajoutez ?n=N aux URLs de l'expéditeur et du récepteur, et le pipe attend que N lecteurs s'attachent, puis miroite le corps à tous simultanément. Les lents ralentissent leur propre connexion — les rapides continuent à couler.

01ÉTAPE 01 · ENTRÉE

Stripe POST vers le pipe

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 s'assemblent.

02ÉTAPE 02 · ASSEMBLAGE

Douze abonnés s'attachent

Chaque abonné est une boucle curl dans un conteneur, qui fait GET sur le même chemin avec ?n=12. Le pipe retient le corps en mémoire jusqu'à ce que le douzième lecteur se connecte — pas de file d'attente sur disque, rien à vider.

03ÉTAPE 03 · DIFFUSION

Fan-out, puis oubli

Une fois tout le monde connecté, le corps est diffusé aux douze à la fois. Un lecteur lent applique la backpressure à son propre socket ; les autres continuent. Quand le dernier lecteur se déconnecte, le pipe oublie le message.

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.

Même URL, même chaîne de requête, des deux côtés. La connexion de l'expéditeur est le broker ; les connexions des lecteurs sont le consumer group. La backpressure est par socket, pas par topic, parce qu'il n'y a pas de topic — il y a un seul corps en vol et douze sockets qui tirent dessus.

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

Les abonnés vont et viennent comme des processus

Ajouter un abonné, c'est un curl de plus dans un conteneur de plus. En retirer un, c'est tuer le curl. Pas de config de broker, pas de rééquilibrage de consumer group, pas de DLQ à vider — la topologie du cluster, c'est juste les processus qui tournent en ce moment.

diff abonnés · 5 dernières minutesaucun rééquilibrage requis
  • + AJOUTÉ
    WHKAUD
    deux nouveaux conteneurs lancés
  • − RETIRÉ
    MIX
    conteneur tué, curl sorti
  • = STABLE
    BILANLLOGFRDSUCSLACRMCDNNOT
    toujours sur le même chemin n=12

Le pipe ne suit pas qui est abonné. Il attend simplement n connexions par événement. Augmentez n des deux côtés et le prochain événement attend le nouvel effectif. Aucun état d'appartenance à corrompre parce qu'il n'y a pas d'appartenance.

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

Ce que vous n'avez plus à exploiter

Chaque ligne ci-dessous est une catégorie de travail qui disparaît quand le broker est le protocole. Aucune infrastructure à provisionner, aucune abstraction à apprendre — juste curl et ?n.

  • Pas de file à provisionner

    Pas de SQS, pas de cluster Kafka, pas d'exchange RabbitMQ. Le pipe est la file, et il vit pour un message à la fois.

  • Pas de comptabilité de consumer group

    Pas d'offsets, pas de commits, pas de rééquilibrages. Le pipe retient le corps jusqu'à ce que n sockets s'attachent — c'est tout le modèle de coordination.

  • Pas de DLQ à vider

    Si l'expéditeur se déconnecte sans n lecteurs prêts, le pipe expire (TTL de 5 min) et Stripe réessaie. Pas de bucket de messages empoisonnés à surveiller.

  • Pas de SDK par langage

    Les abonnés sont des boucles curl. Les expéditeurs sont curl. Le protocole est HTTP. Tout ce qui peut frapper une URL peut rejoindre le cluster.

  • Backpressure par socket

    Un lecteur lent ralentit sa propre connexion. Les onze autres continuent à diffuser à pleine vitesse. Pas de blocage en tête de ligne sur la flotte.

  • Oublieux par défaut

    Le corps disparaît au moment où le dernier lecteur se déconnecte. Pas de politique de rétention à définir, pas de log-compaction à planifier, pas de job de suppression-sur-demande RGPD à écrire.

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

Douze abonnés, une URL, pas de broker.

Les brokers ci-dessous sont les choses que vous installiez avant que le fan-out HTTP ne devienne un paramètre de requête. Le côté droit est ce qui les remplace — un chemin, un n, et douze processus curl qui ne savent pas qu'ils forment un cluster.

CE QUE VOUS N'EXÉCUTEZ PAS
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • Exchanges RabbitMQ
  • Routeurs de webhook personnalisés
CE QUE VOUS APPELEZ À LA PLACE
POST /api/v1/pipe/billing?n=12

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.

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

Ce que cela remplace

Si vous tendez la main vers l'un de ceux-ci pour diffuser un webhook à N consommateurs, le modèle pipe fait le même travail en deux invocations curl — expéditeur d'un côté, récepteurs de l'autre.

  • AWS Lambda + SQS/SNSBroker par topic, IAM par abonné
  • Apache KafkaCluster, ZooKeeper/KRaft, consumer groups
  • Exchanges RabbitMQBindings, vhosts, UI mgmt par env
  • Routeurs de webhook personnalisésService à maintenir, retries à inventer
  • Services Pub/SubFacturation par message, lock-in GCP/AWS
  • Plugins de fan-out HTTPPlugin de gateway par stack, pas de backpressure
use-cases / the-webhook-fan-out-you-didnt-have-to-build / cta

Le fan-out pour lequel vous écriviez un sprint est désormais un paramètre de requête. Ajoutez ?n=12 et expédiez.

Lire la doc pipe
use-cases / the-webhook-fan-out-you-didnt-have-to-build / related

Découvrez les autres