# Fan-Out (/sdks/kotlin/how-to/fan-out)



## Overview [#overview]

<Callout title="This covers the broadcast delivery mode">
  For an overview of both delivery models, see [Multiple Subscribers](/sdks/kotlin/how-to/events/multiple-subscribers). For the load-balance mode instead, see [Consumer Group](/sdks/kotlin/how-to/events/consumer-group).
</Callout>

**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 [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Kotlin SDK installed (`implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1")`)

## Code [#code]

```kotlin title="FanOutExample.kt"
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 [#how-it-works]

* Without a `group` property, 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 [#related]

* [Multiple Subscribers](/sdks/kotlin/how-to/events/multiple-subscribers)
* [Work Queue](/sdks/kotlin/how-to/work-queue)
* [Events Reference](/sdks/kotlin/reference/events)
