Skip to content
TypeUnlocked
StageProduction
DifficultyModerate
JobShare stream
ForBackend devs
ForDev teams
ServicesPipe
ServicesExec
Why HoodyHTTP-native
Why HoodyMultiplayer-default
TypeUnlocked
StageProduction
DifficultyModerate
JobShare stream
ForBackend devs
ForDev teams
ServicesPipe
ServicesExec
Why HoodyHTTP-native
Why HoodyMultiplayer-default
TypeUnlocked
StageProduction
DifficultyModerate
JobShare stream
ForBackend devs
ForDev teams
ServicesPipe
ServicesExec
Why HoodyHTTP-native
Why HoodyMultiplayer-default
TypeUnlocked
StageProduction
DifficultyModerate
JobShare stream
ForBackend devs
ForDev teams
ServicesPipe
ServicesExec
Why HoodyHTTP-native
Why HoodyMultiplayer-default
PIPE · HTTP FAN-OUT

The webhook fan-out you didn't have to build

Stripe POSTs the event body to a pipe path with ?n=12. Twelve subscribers GET the same path with ?n=12. The pipe holds the message until everyone is connected, then streams to all twelve at once. No broker, no consumer group, no DLQ.

Read the pipe docs

One URL. Twelve readers. Backpressure per connection.

Hoody Pipe is HTTP streaming with a multi-receiver mode. Append ?n=N to both the sender and the receiver URLs and the pipe waits until N readers attach, then mirrors the body to all of them simultaneously. The slow ones throttle their own connection — the fast ones keep flowing.

01STEP 01 · INTAKE

Stripe POSTs to the pipe

Your Stripe endpoint forwards the event body straight to /api/v1/pipe/billing?n=12. The connection blocks while the pipe waits for the twelve receivers to assemble.

02STEP 02 · ASSEMBLE

Twelve subscribers attach

Each subscriber is a curl loop in a container, GETing the same path with ?n=12. The pipe holds the body in memory until the twelfth reader connects — no on-disk queue, nothing to flush.

03STEP 03 · STREAM

Fan-out, then forget

Once everyone is connected, the body streams to all twelve at once. A slow reader applies backpressure to its own socket; the others keep going. When the last reader disconnects, the pipe forgets the 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.

Same URL, same query string, both ends. The sender's connection is the broker; the readers' connections are the consumer group. Backpressure is per-socket, not per-topic, because there is no topic — there is one in-flight body and twelve sockets pulling on it.

Subscribers come and go like processes

Adding a subscriber is one more curl in one more container. Removing one is killing the curl. There is no broker config, no consumer-group rebalancing, no DLQ to drain — the cluster topology is just whatever processes happen to be running right now.

subscribers diff · last 5 minutesno rebalancing required
  • + ADDED
    WHKAUD
    two new containers spun up
  • − REMOVED
    MIX
    container killed, curl exited
  • = STABLE
    BILANLLOGFRDSUCSLACRMCDNNOT
    still on the same n=12 path

The pipe doesn't track who is subscribed. It just waits for n connections per event. Bump n on both ends and the next event waits for the new headcount. There is no membership state to corrupt because there is no membership.

What you don't have to operate anymore

Every line below is a category of work that disappears when the broker is the protocol. No infrastructure to provision, no abstractions to learn — just curl and ?n.

  • No queue to provision

    No SQS, no Kafka cluster, no RabbitMQ exchange. The pipe is the queue, and it lives for one message at a time.

  • No consumer-group bookkeeping

    No offsets, no commits, no rebalances. The pipe holds the body until n sockets attach — that is the entire coordination model.

  • No DLQ to drain

    If the sender disconnects without n readers ready, the pipe times out (5-min TTL) and Stripe retries. No poison-message bucket to babysit.

  • No SDK per language

    Subscribers are curl loops. Senders are curl. The protocol is HTTP. Anything that can hit a URL can join the cluster.

  • Per-socket backpressure

    A slow reader throttles its own connection. The other eleven keep streaming at full speed. There is no head-of-line blocking across the fleet.

  • Forgetful by default

    The body is gone the moment the last reader disconnects. No retention policy to set, no log-compaction to schedule, no GDPR delete-on-request job to write.

Twelve subscribers, one URL, no broker.

The brokers below are the things you used to install before HTTP fan-out was a query parameter. The right side is what replaces them — one path, one n, and twelve curl processes that don't know they're a cluster.

WHAT YOU DON'T RUN
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • RabbitMQ exchanges
  • Custom webhook routers
WHAT YOU CALL INSTEAD
POST /api/v1/pipe/billing?n=12

Twelve receivers GET the same path with the same n. The pipe is the broker — and forgets the message the second the last reader hangs up.

What this replaces

If you reach for any of these to broadcast a webhook to N consumers, the pipe model is doing the same job in two curl invocations — sender on one side, receivers on the other.

  • AWS Lambda + SQS/SNSBroker per topic, IAM per subscriber
  • Apache KafkaCluster, ZooKeeper/KRaft, consumer groups
  • RabbitMQ exchangesBindings, vhosts, mgmt UI per env
  • Custom webhook routersService to maintain, retries to invent
  • Pub/Sub servicesPer-message billing, GCP/AWS lock-in
  • HTTP fan-out pluginsGateway plugin per stack, no backpressure

The fan-out you used to write a sprint for is now a query parameter. Append ?n=12 and ship.

Read the pipe docs

Read the others