# Fan-Out (/sdks/csharp/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: an `EventsSubscription` with no `Group` set puts that subscription in broadcast mode instead of load-balanced mode. `SendEventAsync` 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 `SubscribeToEventsAsync` loop hasn't started yet when `SendEventAsync` runs misses that event permanently (use Events Store if you need replay). And `SendEventAsync` is fire-and-forget at the protocol level — it completes once the broker accepts it, not after subscribers process it — so a publisher can outrun subscription setup on a cold start, hence the delay before publishing in this sample.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* C# SDK installed (`dotnet add package KubeMQ.SDK.CSharp`)

## Code [#code]

```csharp title="Program.cs"
// KubeMQ .NET SDK — Patterns: Fan-Out
//
// This example demonstrates the fan-out pattern using events.
// A single publisher sends events that are received by all subscribers
// on the channel. Each subscriber independently receives every event.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Events;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    ClientId = "csharp-patterns-fan-out-client",
});
await client.ConnectAsync();

Console.WriteLine("Connected to KubeMQ server");

var cts = new CancellationTokenSource();

// Start 3 independent subscribers — all will receive every event (no group)
for (int n = 1; n <= 3; n++)
{
    var subscriberName = $"Subscriber-{n}";
    _ = Task.Run(async () =>
    {
        await foreach (var msg in client.SubscribeToEventsAsync(
            new EventsSubscription { Channel = "csharp-patterns.fan-out" }, cts.Token))
        {
            Console.WriteLine($"[{subscriberName}] {Encoding.UTF8.GetString(msg.Body.Span)}");
        }
    });
}

// Allow subscriptions to establish
await Task.Delay(1000);

// Publish events — each subscriber receives all of them
for (var i = 1; i <= 3; i++)
{
    await client.SendEventAsync(new EventMessage
    {
        Channel = "csharp-patterns.fan-out",
        Body = Encoding.UTF8.GetBytes($"Broadcast #{i}"),
    });
    Console.WriteLine($"Published broadcast #{i}");
}

await Task.Delay(2000);
cts.Cancel();

Console.WriteLine("Done.");

```

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

* All three subscribers call `SubscribeToEventsAsync` on the same channel name without a `Group` — this is fan-out mode, where every subscriber receives every message independently.
* Each subscription runs in its own `Task.Run` loop so all three receive concurrently; the `subscriberName` variable is captured per iteration with the loop counter `n`.
* `SendEventAsync` is fire-and-forget at the protocol level — the broker delivers to all active subscribers but does not wait for acknowledgements.
* The 1-second delay after starting subscribers gives the gRPC streams time to register on the broker before the first event is published.

## Related [#related]

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