KubeMQ
ConnectorsMQTTConcepts

Architecture

Inside the MQTT connector — the embedded broker, the bridge hook, the topic mapper, topic-to-pattern mapping, wildcard translation, and cross-protocol interop.

The KubeMQ MQTT connector is an embedded MQTT broker that runs inside kubemq-server. It speaks the standard MQTT protocol (3.1.1 and 5.0) on plain port 1883, TLS port 8883, and WebSocket port 8083 (path /). The connector is opt-in (disabled by default) — enable it with CONNECTORSMQTT_ENABLE=true (Docker) or spec.mqtt.enabled: true (Kubernetes). Any standard MQTT client connects to it with only a broker-address change — no code rewrite, no library swap, no KubeMQ SDK.

Unlike the RabbitMQ (AMQP 0-9-1) connector — which bridges onto exactly one KubeMQ primitive — the MQTT connector bridges onto all five KubeMQ patterns: Events, Events-Store, Queues, Commands, and Queries. The first segment of the topic selects which pattern a publish or subscribe is bound to. That single fact drives the whole mental model.

Protocol stack

A client connection terminates at the embedded broker. A bridge hook intercepts the MQTT CONNECT / PUBLISH / SUBSCRIBE packets, the topic mapper resolves each topic to a KubeMQ (pattern, channel) pair, and the request is dispatched to KubeMQ's core service, which hands it to the message broker. From there it reaches consumers on any KubeMQ transport.

The embedded broker terminates the MQTT connection; the bridge hook and topic mapper translate each packet onto a KubeMQ pattern and channel, and the message broker fans it out to every other KubeMQ transport.

How MQTT maps to KubeMQ

The first topic segment (the prefix) selects the KubeMQ pattern. The remaining segments become the KubeMQ channel, with / translated to ..

The topic prefix selects the KubeMQ pattern; the remaining segments form the channel with / translated to ..

MQTT topic / filterKubeMQ patternDirectionExample topicKubeMQ channel
events/<ch>Eventspublish + subscribeevents/site1/tempsite1.temp
store/<ch>Events-Storepublish + subscribe (StartNewOnly)store/site1/tempsite1.temp
queues/<ch>Queuespublish only (produce)queues/jobs/emailjobs.email
commands/<ch>Commands (RPC)publish only, MQTT 5.0 onlycommands/svc/rebootsvc.reboot
queries/<ch>Queries (RPC)publish only, MQTT 5.0 onlyqueries/svc/statussvc.status
$share/<group>/queues/<ch>Queuessubscribe only (consume), QoS ≥ 1$share/g1/queues/jobs/emailjobs.email
$reply/<clientID>/<suffix>broker-localsubscribe (own namespace only)$reply/client1/inboxnot routed
(prefixless)DefaultPattern (events by default)publish + subscribesite1/tempsite1.temp

Resolution rules:

  • Translation rule: topic path separators / become KubeMQ channel dot separators .. events/site1/sensors/temp → channel site1.sensors.temp.
  • Prefixless topics route to the configured DefaultPattern (events by default; store or none are the alternatives). With none, a prefixless publish returns PUBACK 0x90 and a prefixless subscribe returns SUBACK 0x8F.
  • A literal . inside a topic segment is not escaped — it passes through unchanged and conflates with /. Both events/a.b/c and events/a/b/c map to channel a.b.c. Avoid dots in topic segments.

See Topic grammar for the master table and Topic mapping for narrative guidance.

Wildcard translation

Wildcards are permitted only on Events subscriptions. A wildcard subscribe on any other pattern returns SUBACK 0xA2.

MQTT wildcardKubeMQ wildcardConstraint
+ (single level)*any segment position
# (multi level)>must be the final segment

For example, events/site1/+ subscribes to the channel filter site1.*, and events/# subscribes to >. A store/# subscribe is rejected with SUBACK 0xA2 because wildcards are Events-only.

Overlapping wildcard filters multiply delivery. Each distinct subscribe filter creates an independent bridge registry entry. If several of a client's subscriptions match the same published message, the client receives one copy per matching entry — there is no cross-entry deduplication. Subscribing to #, events/leak/x, and events/# at once delivers three copies of a publish to events/leak/x.

The bridge hook and topic mapper

The embedded broker delegates every protocol decision to a single bridge hook:

  • CONNECT — authenticates the connection (MQTT username / password; the identity is the ClientID) and enforces the protocol-version floor. See Authentication.
  • PUBLISH — the topic mapper resolves the prefix to a pattern and channel; the hook dispatches the message to the KubeMQ core (Events / Events-Store / Queues produce, or an RPC request for Commands / Queries) and translates the result into a PUBACK reason code.
  • SUBSCRIBE — the hook registers the filter in the subscription registry (with wildcard fan-out for Events), or wires a Queue consumer for a $share/<group>/queues/<ch> filter, and returns the SUBACK reason codes.

Two dedicated bridges handle the stateful patterns: a queue bridge drives shared- subscription polling, PUBACK-driven acknowledgment, and redelivery for Queues; an RPC bridge dispatches Commands / Queries requests, routes the response back over the client's response topic, and tracks pending requests against RpcMaxPending.

User Properties ↔ KubeMQ Tags

MQTT 5.0 User Properties map bidirectionally to KubeMQ message Tags. This mapping is MQTT 5.0 only — MQTT 3.1.1 has no user-properties, so nothing is carried in either direction over a v3.1.1 connection.

DirectionMQTT sideKubeMQ sideNotes
Inbound (publish → KubeMQ)Properties.UserTags mapcopied 1:1; duplicate keys: last-wins
Outbound (KubeMQ → subscriber)Properties.UserTags mapinjected on delivery to v5 subscribers only

Per-message caps apply to Events, Events-Store, and Queues publishes: 32 properties and 4096 bytes total (all keys + values). Exceeding either cap rejects the message — PUBACK 0x97 on v5, or a silent drop on v3.1.1.

Cross-protocol interop

The KubeMQ core service is the shared message bus for all KubeMQ connectors, so MQTT interoperates transparently with every other transport. An MQTT publish to events/it/cross is received by a gRPC SubscribeEvents on channel it.cross, and vice-versa. The same holds for Events-Store, Queues, Commands, and Queries — any connector (gRPC, REST, CloudEvents, MQTT) can interoperate on the same channels.

The same KubeMQ channel backs both connectors, so an MQTT client and a gRPC/REST client interoperate transparently.

Was this page helpful?

On this page