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



## Overview [#overview]

**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: building an `EventsSubscription` without calling `.group(...)` 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 name silently turns broadcast into competing-consumer load-balancing with no error raised. Events are not persisted — a subscriber that hasn't called `subscribeToEvents()` yet when `publishEvent()` runs misses that event permanently (use Events Store if you need replay). And `publishEvent()` is fire-and-forget — it returns as soon as the broker accepts the send, not after subscribers process it — so a publisher can outrun subscription setup on a cold start, which is why this sample sleeps briefly before publishing.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Java SDK installed (`implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1'` (Gradle) or Maven dependency from [Getting Started](/sdks/java))

## Code [#code]

```java title="FanOutExample.java"
package io.kubemq.example.patterns;

import io.kubemq.sdk.common.ServerInfo;
import io.kubemq.sdk.pubsub.*;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Fan-Out Pattern Example
 *
 * Demonstrates the fan-out pattern where one publisher sends to multiple subscribers.
 */
public class FanOutExample {

    private static final String ADDRESS = "localhost:50000";
    private static final String CLIENT_ID = "java-patterns-fan-out-client";
    private static final String CHANNEL = "java-patterns.fan-out";

    public static void main(String[] args) throws InterruptedException {
        // Create a client connected to the KubeMQ server
        PubSubClient client = PubSubClient.builder().address(ADDRESS).clientId(CLIENT_ID).build();
        ServerInfo info = client.ping();
        System.out.println("Connected to: " + info.getHost());
        // Create the events channel
        client.createEventsChannel(CHANNEL);

        // Subscribe multiple handlers (each receives all messages)
        int numSubscribers = 3;
        int numMessages = 3;
        AtomicInteger[] counts = new AtomicInteger[numSubscribers];
        CountDownLatch latch = new CountDownLatch(numSubscribers * numMessages);
        EventsSubscription[] subs = new EventsSubscription[numSubscribers];

        for (int i = 0; i < numSubscribers; i++) {
            final int id = i + 1;
            counts[i] = new AtomicInteger(0);
            final AtomicInteger counter = counts[i];

            subs[i] = EventsSubscription.builder()
                    .channel(CHANNEL)
                    .onReceiveEventCallback(event -> {
                        counter.incrementAndGet();
                        System.out.println("  Subscriber " + id + ": " + new String(event.getBody()));
                        latch.countDown();
                    })
                    .onErrorCallback(err -> {}).build();
            // Subscribe each subscriber to the channel
            client.subscribeToEvents(subs[i]);
        }
        Thread.sleep(500);

        // Publish messages (fan-out to all subscribers)
        System.out.println("Publishing " + numMessages + " messages to " + numSubscribers + " subscribers...\n");
        for (int i = 1; i <= numMessages; i++) {
            client.publishEvent(EventMessage.builder()
                    .id("fan-" + i).channel(CHANNEL)
                    .body(("Broadcast #" + i).getBytes()).build());
            Thread.sleep(100);
        }

        latch.await(5, TimeUnit.SECONDS);
        System.out.println("\nResults:");
        for (int i = 0; i < numSubscribers; i++) {
            System.out.println("  Subscriber " + (i + 1) + ": " + counts[i].get() + " messages");
        }

        // Clean up resources
        for (EventsSubscription s : subs) { s.cancel(); }
        client.deleteEventsChannel(CHANNEL);
        client.close();
    }
}

```

## How It Works [#how-it-works]

* A single `PubSubClient` creates three `EventsSubscription` objects on the same channel without a `group()` — every subscriber receives every published message independently, which is the fan-out property.
* Each subscriber is wired with its own `AtomicInteger` counter and shares a `CountDownLatch` initialized to `numSubscribers * numMessages`; `latch.await()` blocks main until all deliveries are confirmed.
* `publishEvent()` is fire-and-forget: it enqueues the gRPC send and returns immediately without waiting for subscriber acknowledgements.
* `Thread.sleep(500)` after subscribing gives the SDK time to register all three subscriptions with the broker before publishing begins; this avoids race conditions in examples but is not needed in long-running services.

## Related [#related]

* [Pattern overview](/learn/guides/choosing-a-pattern)
* [Java SDK Reference](/sdks/java/reference)
* [Request-Reply](/sdks/java/how-to/request-reply)
* [Work Queue](/sdks/java/how-to/work-queue)
