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 / filter | KubeMQ pattern | Direction | Example topic | KubeMQ channel |
|---|---|---|---|---|
events/<ch> | Events | publish + subscribe | events/site1/temp | site1.temp |
store/<ch> | Events-Store | publish + subscribe (StartNewOnly) | store/site1/temp | site1.temp |
queues/<ch> | Queues | publish only (produce) | queues/jobs/email | jobs.email |
commands/<ch> | Commands (RPC) | publish only, MQTT 5.0 only | commands/svc/reboot | svc.reboot |
queries/<ch> | Queries (RPC) | publish only, MQTT 5.0 only | queries/svc/status | svc.status |
$share/<group>/queues/<ch> | Queues | subscribe only (consume), QoS ≥ 1 | $share/g1/queues/jobs/email | jobs.email |
$reply/<clientID>/<suffix> | broker-local | subscribe (own namespace only) | $reply/client1/inbox | not routed |
| (prefixless) | DefaultPattern (events by default) | publish + subscribe | site1/temp | site1.temp |
Resolution rules:
- Translation rule: topic path separators
/become KubeMQ channel dot separators..events/site1/sensors/temp→ channelsite1.sensors.temp. - Prefixless topics route to the configured
DefaultPattern(eventsby default;storeornoneare the alternatives). Withnone, a prefixless publish returns PUBACK0x90and a prefixless subscribe returns SUBACK0x8F. - A literal
.inside a topic segment is not escaped — it passes through unchanged and conflates with/. Bothevents/a.b/candevents/a/b/cmap to channela.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 wildcard | KubeMQ wildcard | Constraint |
|---|---|---|
+ (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.
| Direction | MQTT side | KubeMQ side | Notes |
|---|---|---|---|
| Inbound (publish → KubeMQ) | Properties.User | Tags map | copied 1:1; duplicate keys: last-wins |
| Outbound (KubeMQ → subscriber) | Properties.User | Tags map | injected 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.
Related
Topic grammar
The master topic grammar — prefixes, wildcards, $share queue consume, and $reply.
Capabilities
The full CONNACK capability set, forced values, and the per-message property caps.
Events
Fire-and-forget pub/sub over MQTT — wildcards and User-Properties as Tags.
Reason codes
The PUBACK / SUBACK / CONNACK reason codes the connector returns and what triggers each.
Was this page helpful?