# Basic Pub/Sub (/sdks/rust/tutorials/basic-pubsub)



## Overview [#overview]

This tutorial builds the "hello world" of KubeMQ messaging: a publisher and a subscriber talking over the **Events** pattern. Events are fire-and-forget — the broker fans a message out to every subscriber currently listening on the channel and moves on. There's no persistence, no acknowledgment, and no replay, which makes this the pattern to reach for when you need low-latency, high-throughput broadcast (metrics ticks, live status updates, cache-invalidation signals) and can tolerate losing a message if nobody is listening at the moment it's sent.

You'll wire up `subscribe_to_events` with an async callback, give the subscription a moment to register with the server, then build an event with `EventBuilder` and publish it with `send_event`. The empty consumer-group argument means fan-out delivery: every connected subscriber gets its own copy, as opposed to a consumer group where only one member would receive it. &#x2A;*Gotchas:** if the subscriber isn't fully established before you publish, the event is simply gone — there's no queue catching it, which is why the sample sleeps briefly before sending; and because delivery isn't acknowledged, a crashed or disconnected subscriber never knows it missed anything.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Rust SDK installed (`cargo add kubemq`)

## Code [#code]

```rust title="main.rs"
use kubemq::prelude::*;
use kubemq::{EventBuilder, Subscription};
use std::time::Duration;

#[tokio::main]
async fn main() -> kubemq::Result<()> {
    let client = KubemqClient::builder()
        .host("localhost")
        .port(50000)
        .build()
        .await?;

    let channel = "rust-events.basic-pubsub";

    let sub: Subscription = client
        .subscribe_to_events(
            channel,
            "",
            |event| {
                Box::pin(async move {
                    println!(
                        "Received event: id={}, channel={}, body={} bytes",
                        event.id,
                        event.channel,
                        event.body.len()
                    );
                })
            },
            None,
        )
        .await?;

    tokio::time::sleep(Duration::from_millis(500)).await;

    let event = EventBuilder::new()
        .channel(channel)
        .metadata("example-metadata")
        .body(b"Hello KubeMQ!".to_vec())
        .build();

    client.send_event(event).await?;
    println!("Event sent to channel: {}", channel);

    tokio::time::sleep(Duration::from_secs(2)).await;

    sub.unsubscribe().await;
    client.close().await?;
    Ok(())
}
```

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

* The subscription callback uses `Box::pin(async move { ... })` — the standard Rust pattern for async closures.
* An empty group string `""` means fan-out delivery to all subscribers.
* Review timeouts, channel names, and client IDs before running against shared environments.
* Run the program while the server from the prerequisites is available.

## Related [#related]

* [Events overview](/learn/events)
* [Rust SDK Reference](/sdks/rust/reference/events)
* [Consumer Group](/sdks/rust/how-to/events/consumer-group)
* [Wildcard Subscription](/sdks/rust/how-to/events/wildcard-subscription)
