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)
| Syntax | Meaning |
|---|---|
events:channel-a;events:channel-b | Two event channels |
events:live;events_store:archive | Event + persistent copy |
events:notify;queues:process | Broadcast + reliable work queue |
events:a;events_store:b;queues:c | All 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.
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")
}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()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");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();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");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()#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;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(())
}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{: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.
err = client.SendEvent(ctx, kubemq.NewEvent().
SetChannel("events:order-notify;queues:order-process").
SetMetadata("order.created").
SetBody([]byte(`{"orderId":"ORD-200","amount":129.00}`)),
)client.send_event(
EventMessage(
channel="events:order-notify;queues:order-process",
metadata="order.created",
body=b'{"orderId":"ORD-200","amount":129.00}',
)
)await client.sendEvent({
channel: "events:order-notify;queues:order-process",
metadata: "order.created",
body: Buffer.from('{"orderId":"ORD-200","amount":129.00}'),
});client.sendEventsMessage(EventMessage.builder()
.channel("events:order-notify;queues:order-process")
.metadata("order.created")
.body("{\"orderId\":\"ORD-200\",\"amount\":129.00}".getBytes())
.build());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}"),
});client.sendEvent(EventMessage(
channel = "events:order-notify;queues:order-process",
metadata = "order.created",
body = """{"orderId":"ORD-200","amount":129.00}""".toByteArray(),
))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);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?;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)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.
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}`)),
)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}',
)
)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}'),
});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());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}"),
});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(),
))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);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?;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)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?