Fan-Out
Broadcast messages to multiple independent subscribers
Overview
This covers the broadcast delivery mode
For an overview of both delivery models, see Multiple Subscribers. For the load-balance mode instead, see Consumer Group.
Fan-out is the default delivery behavior of KubeMQ Events pub/sub: when subscribers don't join a consumer group, every subscriber gets its own independent copy of each published event. Reach for it whenever several unrelated services need to react to the same occurrence — an order placed, a config change, an audit event — without the publisher knowing or caring who's listening, and without one subscriber's slowness affecting another's delivery.
The mechanism is simply omission: a subscribeToEvents { channel = ... } block with no group property puts that subscription in broadcast mode instead of load-balanced mode. publishEvent doesn't change at all — the publisher sends once, and the broker independently pushes a copy to every active subscriber on the channel.
Gotchas: fan-out is opt-out by default, so a typo'd or accidentally shared group value silently turns broadcast into competing-consumer load-balancing with no error raised. Events are not persisted — a subscriber whose collect hasn't started yet when publishEvent runs misses that event permanently (use Events Store if you need replay). And publishEvent returns as soon as the broker accepts it, not after subscribers process it, so a publisher can outrun subscription setup on a cold start — hence the short delay before publishing in this sample.
Prerequisites
- KubeMQ server running on
localhost:50000 - Kotlin SDK installed (
implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1"))
Code
package io.kubemq.sdk.examples.patterns
import io.kubemq.sdk.client.KubeMQClient
import io.kubemq.sdk.pubsub.eventMessage
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.util.concurrent.atomic.AtomicInteger
private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-patterns-fan-out"
private const val CHANNEL = "kotlin-patterns.fan-out"
fun main() = runBlocking {
val client = KubeMQClient.pubSub {
address = ADDRESS
clientId = CLIENT_ID
}
client.use {
val numSubscribers = 3
val numMessages = 3
val counts = Array(numSubscribers) { AtomicInteger(0) }
val totalReceived = AtomicInteger(0)
val expectedTotal = numSubscribers * numMessages
// Subscribe multiple handlers (each receives all messages -- no group)
val jobs = (0 until numSubscribers).map { i ->
launch {
client.subscribeToEvents {
channel = CHANNEL
}.collect { msg ->
counts[i].incrementAndGet()
println(" Subscriber ${i + 1}: ${String(msg.body)}")
totalReceived.incrementAndGet()
}
}
}
delay(500)
// Publish messages (fan-out to all subscribers)
println("Publishing $numMessages messages to $numSubscribers subscribers...\n")
repeat(numMessages) { i ->
client.publishEvent(eventMessage {
channel = CHANNEL
body = "Broadcast #${i + 1}".toByteArray()
})
delay(100)
}
delay(2000)
println("\nResults:")
for (i in 0 until numSubscribers) {
println(" Subscriber ${i + 1}: ${counts[i].get()} messages")
}
jobs.forEach { it.cancel() }
println("Done.")
}
}How It Works
- Without a
groupproperty, all subscribers receive every published message (fan-out/broadcast). - Each of the 3 subscribers receives all 3 messages, for a total of 9 deliveries.
- Fan-out is useful for notifications, audit logging, cache invalidation, or event-driven architectures.
- To switch to competing consumers (load balancing), add
group = "group-name"to subscriptions.
Related
Was this page helpful?