Cross-Protocol Routing
Cross-protocol routing lets producers and consumers using different protocols communicate directly through the same FlowMQ routing core.
FlowMQ's core messaging model is protocol-independent: producers publish messages with topics, destinations bind to topic filters, and consumers receive messages from destinations. See Messaging Model for the core concepts.
This page focuses on how that model is exposed across protocols.
How It Works
When a client publishes through a protocol endpoint, FlowMQ associates the protocol message with an internal routing topic. This topic is the routing address used by FlowMQ's protocol-independent routing engine.
- A producer publishes using its protocol-native target.
- FlowMQ associates the message with an internal routing topic derived from that target.
- FlowMQ routes the message to destinations whose filters match the topic.
- Consumers receive the message from those destinations using the protocol interface they connect with.
The producer does not need to know which protocol the consumer uses. The consumer does not need to know which protocol produced the message.
MQTT Mapping
MQTT topics already use the same hierarchical shape as FlowMQ topics, so the publish topic maps directly to the internal routing topic.
| MQTT concept | Example | FlowMQ model |
|---|---|---|
| Publish topic | sensors/factory-1/temperature | Internal routing topic sensors/factory-1/temperature |
| Subscribe filter | sensors/# | Subscription filter sensors/# |
Kafka Mapping
Kafka exposes writes and reads through Kafka topics, partitions, and offsets. FlowMQ maps Kafka records onto the core model by deriving an internal routing topic from the Kafka topic name, then appending matching messages to streams.
Publishing
When a Kafka producer sends a record, FlowMQ derives the internal routing topic from the Kafka topic name. By convention, dot-separated Kafka topic names map to slash-separated internal routing topics. The record key, value, headers, and timestamp are preserved as message data or metadata, but they do not participate in topic derivation.
| Kafka publish target | FlowMQ internal routing topic |
|---|---|
Topic orders.created | orders/created |
Topic orders | orders |
For example, a Kafka record produced to Kafka topic a.b.c is routed as a message with internal topic a/b/c. An MQTT client subscribed to a/b/c can receive that message directly.
Streams
A FlowMQ stream is exposed to Kafka clients as a Kafka topic with the same name. By default, that stream binds to the internal routing topic derived from the Kafka topic name, so records produced through Kafka are appended to the stream that Kafka consumers read.
| FlowMQ model | Kafka protocol view |
|---|---|
Stream orders.created | Kafka topic orders.created |
Topic filter orders/created | Default binding for stream orders.created |
Stream partition 0 | Kafka partition 0 |
Offset 42 in that stream partition | Kafka offset 42 |
The same binding also enables other protocols to write into Kafka-visible streams. For example, an MQTT message published to orders/created matches the default binding for stream orders.created, so Kafka consumers subscribed to topic orders.created can read it.
A stream can also have additional bindings to more topic filters, allowing the same Kafka-visible stream to collect messages from multiple internal routing topics. See Streaming to learn more.
AMQP Mapping
AMQP exposes routing through exchanges, routing keys, queues, and bindings. FlowMQ maps AMQP publish operations and queue bindings onto the core model by deriving internal routing topics and matching those topics against queue bindings.
Publishing
When an AMQP client publishes a message, FlowMQ derives the internal routing topic from the AMQP exchange, routing_key, and exchange type. AMQP message properties and headers are preserved as message metadata, but they do not participate in topic derivation.
For direct and topic exchanges, FlowMQ combines the exchange name with the routing key. Dot-separated routing key words map to slash-separated topic levels.
| AMQP publish target | FlowMQ internal routing topic |
|---|---|
Exchange orders, routing key created.us | orders/created/us |
Exchange orders, routing key created | orders/created |
For fanout exchanges, the routing key is ignored as in AMQP. FlowMQ uses the exchange name as the internal routing topic:
| AMQP publish target | FlowMQ internal routing topic |
|---|---|
Fanout exchange notifications, any routing key | notifications |
The AMQP default exchange (exchange="") keeps its AMQP direct-to-queue behavior. Its routing key identifies the target queue, so FlowMQ treats it as direct delivery to the queue with that name instead of exposing it as a general cross-protocol topic.
Queues and Bindings
An AMQP queue maps directly to a FlowMQ queue destination:
| AMQP concept | FlowMQ model |
|---|---|
Queue order-processing | Queue destination order-processing |
AMQP queue bindings define how that queue matches derived internal routing topics.
For direct exchanges, the binding key is an exact routing key. AMQP wildcard characters have no wildcard meaning in direct exchanges.
| AMQP binding | FlowMQ matching rule |
|---|---|
Exchange orders, binding key created.us | Match internal topic orders/created/us |
For topic exchanges, AMQP topic binding keys are compiled into FlowMQ topic filters when they can be represented by FlowMQ's filter syntax.
| AMQP topic binding | FlowMQ queue binding filter |
|---|---|
Exchange orders, binding key created.* | orders/created/+ |
Exchange orders, binding key created.# | orders/created/# |
FlowMQ's general topic filter model uses MQTT-style wildcards: + matches one level, and # matches zero or more levels at the end of a filter. AMQP topic exchanges also allow # in positions that cannot be represented as a FlowMQ topic filter, such as #.created or created.#.high.
FlowMQ still supports those AMQP-native bindings for AMQP queues. They are evaluated with AMQP topic-exchange matching rules against the message's derived routing address, but they are not exposed as FlowMQ topic filters.
For example, an AMQP message published to topic exchange orders with routing key created.us is routed as a message with internal topic orders/created/us. An AMQP queue bound to exchange orders with topic binding key created.* can receive the message because that binding compiles to FlowMQ filter orders/created/+. An MQTT client subscribed to orders/created/+ can also receive this message directly.
Routing Across Protocols
Cross-protocol routing works because messages from different protocols are associated with internal topics in the same routing model. After a message has an internal topic, FlowMQ routes it without depending on the protocol that produced it.
If the internal topic matches a destination's filter, or an AMQP-native queue binding evaluated by the AMQP adapter, the message is delivered to that destination. Consumers can then receive the message through any protocol interface that exposes that destination or subscription.
Common patterns include:
- Device telemetry published through a lightweight protocol and stored in a stream for processing.
- Application events published by a service and pushed to online clients through subscriptions.
- Jobs published by one client and consumed from a queue by workers using another protocol.
Because routing is handled by FlowMQ's core, there is no external bridge between protocol-specific brokers.
MQTT to Kafka Example
An MQTT device publishes telemetry to:
sensors/factory-1/temperatureA stream named sensor.telemetry is bound to:
sensors/#FlowMQ routes the message to the stream because the MQTT publish topic maps to internal topic sensors/factory-1/temperature, which matches the stream filter sensors/#.
A Kafka consumer reads from the stream through the Kafka protocol:
sensor.telemetryThe MQTT device does not need to know that the message is stored in a stream or consumed by a Kafka client.
Kafka to MQTT Example
A backend service sends a device control command through Kafka:
devices.vehicle-42.commandsFlowMQ maps that Kafka topic to the internal topic:
devices/vehicle-42/commandsThe device is connected through MQTT and subscribes to:
devices/vehicle-42/commandsFlowMQ routes the command to the MQTT subscription because devices/vehicle-42/commands matches the device's subscription. The backend service can use a Kafka client only and does not need an MQTT client to communicate with devices.
Why This Matters
Cross-protocol routing helps you:
- Let each application use its native protocol interface while still exchanging messages through FlowMQ.
- Avoid deploying separate message brokers for different protocols.
- Replace protocol-specific bridges with native routing inside one broker.
- Share data between device, backend, and analytics systems without duplicating ingestion pipelines.
- Preserve protocol-specific client behavior while routing messages through the same internal model.