Multiple Subscribers
Deliver the same KubeMQ events to multiple independent subscribers in Node.js, fanning each message out to every listener.
Overview
Fan-out delivery lets several independent consumers each get their own copy of every event published on a channel — the pattern behind broadcasting a notification to every connected service or feeding the same stream to a cache invalidator and a metrics collector at once. Reach for it whenever multiple, unrelated pieces of code all need to react to the same event, rather than compete for it.
It works by calling subscribeToEvents more than once for the same channel while leaving the group option empty. Each call opens its own stream, and the broker treats every subscriber with no group as broadcast: publishing one event delivers it to every open stream — the opposite of a consumer group, where subscribers sharing a group name split events among themselves for load balancing.
Gotchas: Events pub/sub has no durability — a subscriber that hasn't finished subscribing yet, or that disconnects, simply misses events published in that window; there's no redelivery. Mixing a non-empty group into one subscriber on the same channel silently turns broadcast into load-balancing for it. And because delivery is fully concurrent, shared state your callbacks touch needs its own synchronization.
Prerequisites
- KubeMQ server running on
localhost:50000 - Node.js SDK installed (
npm install kubemq-js)
Code
/**
* Example: Multiple Subscribers on the Same Channel
*
* Demonstrates that multiple subscribers on the same channel each receive
* a copy of every published event (fan-out). Use the `group` option for
* load-balanced (competing consumer) behavior instead.
*
* Prerequisites:
* - KubeMQ server running on localhost:50000
*
* Run: npx tsx examples/events/multiple-subscribers.ts
*/
import { KubeMQClient, createEventMessage } from 'kubemq-js';
async function main(): Promise<void> {
const client = await KubeMQClient.create({
address: 'localhost:50000',
clientId: 'js-events-multiple-subscribers-client',
});
try {
// Both subscribers receive every event (fan-out).
const sub1 = client.subscribeToEvents({
channel: 'js-events.multiple-subscribers',
onEvent: (event) => {
console.log('[Subscriber A]', new TextDecoder().decode(event.body));
},
onError: (err) => {
console.error('Sub A error:', err.message);
},
});
const sub2 = client.subscribeToEvents({
channel: 'js-events.multiple-subscribers',
onEvent: (event) => {
console.log('[Subscriber B]', new TextDecoder().decode(event.body));
},
onError: (err) => {
console.error('Sub B error:', err.message);
},
});
// Allow subscriptions to fully establish on the server.
await new Promise((resolve) => setTimeout(resolve, 1000));
await client.sendEvent(
createEventMessage({ channel: 'js-events.multiple-subscribers', body: 'cpu_usage=72%' }),
);
await new Promise((resolve) => setTimeout(resolve, 1000));
sub1.cancel();
sub2.cancel();
} finally {
await client.close();
}
}
main().catch(console.error);
How It Works
sub1andsub2both callsubscribeToEvents()on the same channel with nogroupoption — this is fan-out mode: every published event is delivered to all active subscribers independently.- The 1-second wait after subscribing ensures both gRPC streams are registered on the server before the single event is published.
- Because the SDK callbacks run on the Node.js event loop sequentially, both
[Subscriber A]and[Subscriber B]lines appear in output for the single sent event. - To switch to competing-consumer (load-balanced) behavior instead, set
group: 'workers'on both subscriptions.
Related
Was this page helpful?