KubeMQ
LearnGuides

Channel Routing

Publish to multiple channels and patterns simultaneously using KubeMQ routing syntax.

New to channel naming and fan-out? Start with Channels & Routing in Fundamentals to understand how channels and patterns work before applying the routing syntax below.

Routing Syntax

KubeMQ supports publishing to multiple channels and patterns in a single operation using a routing syntax built into the channel name:

  • ; separates multiple channel targets
  • : prefixes the pattern type (events, events_store, queues)
SyntaxMeaning
events:channel-a;events:channel-bTwo event channels
events:live;events_store:archiveEvent + persistent copy
events:notify;queues:processBroadcast + reliable work queue
events:a;events_store:b;queues:cAll three patterns

Routing is transparent to subscribers — each target channel receives the message as if it were published directly.

Examples

Events + Events Store

Publish an order event to a live channel and persist a copy to an archive channel in a single call.

route_events_store.go
package main

import (
    "context"
    "log"

    "github.com/kubemq-io/kubemq-go/v2"
)

func main() {
    ctx := context.Background()
    client, err := kubemq.NewClient(ctx,
        kubemq.WithAddress("localhost", 50000),
        kubemq.WithClientId("order-router"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    err = client.SendEvent(ctx, kubemq.NewEvent().
        SetChannel("events:order-live;events_store:order-archive").
        SetMetadata("order.created").
        SetBody([]byte(`{"orderId":"ORD-100","amount":59.99}`)),
    )
    if err != nil {
        log.Fatal(err)
    }
    log.Println("Routed to events + events_store")
}
route_events_store.py
from kubemq.pubsub import Client as PubSubClient, EventMessage

client = PubSubClient(address="localhost:50000", client_id="order-router")

client.send_event(
    EventMessage(
        channel="events:order-live;events_store:order-archive",
        metadata="order.created",
        body=b'{"orderId":"ORD-100","amount":59.99}',
    )
)
print("Routed to events + events_store")
client.close()
route_events_store.js
const { KubeMQClient } = require("kubemq-js");

const client = new KubeMQClient({ address: "localhost:50000", clientId: "order-router" });

await client.sendEvent({
  channel: "events:order-live;events_store:order-archive",
  metadata: "order.created",
  body: Buffer.from('{"orderId":"ORD-100","amount":59.99}'),
});
console.log("Routed to events + events_store");
RouteEventsStore.java
PubSubClient client = PubSubClient.builder()
    .address("localhost:50000")
    .clientId("order-router")
    .build();

client.sendEventsMessage(EventMessage.builder()
    .channel("events:order-live;events_store:order-archive")
    .metadata("order.created")
    .body("{\"orderId\":\"ORD-100\",\"amount\":59.99}".getBytes())
    .build());
System.out.println("Routed to events + events_store");
client.close();
RouteEventsStore.cs
await using var client = new KubeMQClient(new KubeMQClientOptions
{
    Address = "localhost:50000",
    ClientId = "order-router"
});
await client.ConnectAsync();

await client.SendEventAsync(new EventMessage
{
    Channel = "events:order-live;events_store:order-archive",
    Metadata = "order.created",
    Body = Encoding.UTF8.GetBytes("{\"orderId\":\"ORD-100\",\"amount\":59.99}"),
});
Console.WriteLine("Routed to events + events_store");
RouteEventsStore.kt
val client = PubSubClient("localhost:50000")

client.sendEvent(EventMessage(
    channel = "events:order-live;events_store:order-archive",
    metadata = "order.created",
    body = """{"orderId":"ORD-100","amount":59.99}""".toByteArray(),
))
println("Routed to events + events_store")
client.close()
route_events_store.cpp
#include <kubemq/client.h>
#include <iostream>

auto client = kubemq::PubSubClient("localhost:50000");

kubemq::EventMessage event;
event.channel = "events:order-live;events_store:order-archive";
event.metadata = "order.created";
event.body = R"({"orderId":"ORD-100","amount":59.99})";

client.sendEvent(event);
std::cout << "Routed to events + events_store" << std::endl;
route_events_store.rs
use kubemq::prelude::*;
use kubemq::EventBuilder;

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

    let event = EventBuilder::new()
        .channel("events:order-live;events_store:order-archive")
        .metadata("order.created")
        .body(br#"{"orderId":"ORD-100","amount":59.99}"#.to_vec())
        .build();

    client.send_event(event).await?;
    println!("Routed to events + events_store");

    client.close().await?;
    Ok(())
}
route_events_store.rb
require 'kubemq'

client = KubeMQ::PubSubClient.new(address: 'localhost:50000', client_id: 'order-router')

msg = KubeMQ::PubSub::EventMessage.new(
  channel: 'events:order-live;events_store:order-archive',
  metadata: 'order.created',
  body: '{"orderId":"ORD-100","amount":59.99}'
)
client.send_event(msg)
puts 'Routed to events + events_store'
client.close
route_events_store.exs
{:ok, client} = KubeMQ.Client.start_link(address: "localhost:50000", client_id: "order-router")

event = KubeMQ.Event.new(
  channel: "events:order-live;events_store:order-archive",
  metadata: "order.created",
  body: ~s({"orderId":"ORD-100","amount":59.99})
)

:ok = KubeMQ.Client.send_event(client, event)
IO.puts("Routed to events + events_store")
KubeMQ.Client.close(client)

Events + Queue

Broadcast an event for real-time subscribers and queue a copy for reliable processing.

route_events_queue.go
err = client.SendEvent(ctx, kubemq.NewEvent().
    SetChannel("events:order-notify;queues:order-process").
    SetMetadata("order.created").
    SetBody([]byte(`{"orderId":"ORD-200","amount":129.00}`)),
)
route_events_queue.py
client.send_event(
    EventMessage(
        channel="events:order-notify;queues:order-process",
        metadata="order.created",
        body=b'{"orderId":"ORD-200","amount":129.00}',
    )
)
route_events_queue.js
await client.sendEvent({
  channel: "events:order-notify;queues:order-process",
  metadata: "order.created",
  body: Buffer.from('{"orderId":"ORD-200","amount":129.00}'),
});
RouteEventsQueue.java
client.sendEventsMessage(EventMessage.builder()
    .channel("events:order-notify;queues:order-process")
    .metadata("order.created")
    .body("{\"orderId\":\"ORD-200\",\"amount\":129.00}".getBytes())
    .build());
RouteEventsQueue.cs
await client.SendEventAsync(new EventMessage
{
    Channel = "events:order-notify;queues:order-process",
    Metadata = "order.created",
    Body = Encoding.UTF8.GetBytes("{\"orderId\":\"ORD-200\",\"amount\":129.00}"),
});
RouteEventsQueue.kt
client.sendEvent(EventMessage(
    channel = "events:order-notify;queues:order-process",
    metadata = "order.created",
    body = """{"orderId":"ORD-200","amount":129.00}""".toByteArray(),
))
route_events_queue.cpp
kubemq::EventMessage event;
event.channel = "events:order-notify;queues:order-process";
event.metadata = "order.created";
event.body = R"({"orderId":"ORD-200","amount":129.00})";
client.sendEvent(event);
route_events_queue.rs
let event = EventBuilder::new()
    .channel("events:order-notify;queues:order-process")
    .metadata("order.created")
    .body(br#"{"orderId":"ORD-200","amount":129.00}"#.to_vec())
    .build();
client.send_event(event).await?;
route_events_queue.rb
msg = KubeMQ::PubSub::EventMessage.new(
  channel: 'events:order-notify;queues:order-process',
  metadata: 'order.created',
  body: '{"orderId":"ORD-200","amount":129.00}'
)
client.send_event(msg)
route_events_queue.exs
event = KubeMQ.Event.new(
  channel: "events:order-notify;queues:order-process",
  metadata: "order.created",
  body: ~s({"orderId":"ORD-200","amount":129.00})
)
:ok = KubeMQ.Client.send_event(client, event)

All Three Patterns

Route a single publish to an event channel, persistent store, and a work queue simultaneously.

route_all.go
err = client.SendEvent(ctx, kubemq.NewEvent().
    SetChannel("events:order-live;events_store:order-archive;queues:order-fulfill").
    SetMetadata("order.created").
    SetBody([]byte(`{"orderId":"ORD-300","amount":349.99}`)),
)
route_all.py
client.send_event(
    EventMessage(
        channel="events:order-live;events_store:order-archive;queues:order-fulfill",
        metadata="order.created",
        body=b'{"orderId":"ORD-300","amount":349.99}',
    )
)
route_all.js
await client.sendEvent({
  channel: "events:order-live;events_store:order-archive;queues:order-fulfill",
  metadata: "order.created",
  body: Buffer.from('{"orderId":"ORD-300","amount":349.99}'),
});
RouteAll.java
client.sendEventsMessage(EventMessage.builder()
    .channel("events:order-live;events_store:order-archive;queues:order-fulfill")
    .metadata("order.created")
    .body("{\"orderId\":\"ORD-300\",\"amount\":349.99}".getBytes())
    .build());
RouteAll.cs
await client.SendEventAsync(new EventMessage
{
    Channel = "events:order-live;events_store:order-archive;queues:order-fulfill",
    Metadata = "order.created",
    Body = Encoding.UTF8.GetBytes("{\"orderId\":\"ORD-300\",\"amount\":349.99}"),
});
RouteAll.kt
client.sendEvent(EventMessage(
    channel = "events:order-live;events_store:order-archive;queues:order-fulfill",
    metadata = "order.created",
    body = """{"orderId":"ORD-300","amount":349.99}""".toByteArray(),
))
route_all.cpp
kubemq::EventMessage event;
event.channel = "events:order-live;events_store:order-archive;queues:order-fulfill";
event.metadata = "order.created";
event.body = R"({"orderId":"ORD-300","amount":349.99})";
client.sendEvent(event);
route_all.rs
let event = EventBuilder::new()
    .channel("events:order-live;events_store:order-archive;queues:order-fulfill")
    .metadata("order.created")
    .body(br#"{"orderId":"ORD-300","amount":349.99}"#.to_vec())
    .build();
client.send_event(event).await?;
route_all.rb
msg = KubeMQ::PubSub::EventMessage.new(
  channel: 'events:order-live;events_store:order-archive;queues:order-fulfill',
  metadata: 'order.created',
  body: '{"orderId":"ORD-300","amount":349.99}'
)
client.send_event(msg)
route_all.exs
event = KubeMQ.Event.new(
  channel: "events:order-live;events_store:order-archive;queues:order-fulfill",
  metadata: "order.created",
  body: ~s({"orderId":"ORD-300","amount":349.99})
)
:ok = KubeMQ.Client.send_event(client, event)

How Routing Works Internally

When the server receives a channel string containing ; or : delimiters, it splits the targets and fans the message out to each pattern and channel independently.

Each target is processed independently — a failure on one target does not affect the others. The server returns an error only if the routing syntax itself is invalid.

Key Points

  • Atomic fan-out — a single SDK call routes to all targets without client-side loops
  • Mixed patterns — combine events, events_store, and queues in any combination
  • Independent delivery — each target processes the message according to its own pattern semantics
  • Subscriber transparency — subscribers see messages as if published directly to their channel

Was this page helpful?

On this page