Skip to content
Stand with Ukraine flag

MQTT protocol

MQTT is the wire protocol TBMQ speaks. This page covers how TBMQ implements MQTT — the versions it accepts, the endpoints clients connect to, the protocol limits it enforces, and the MQTT 5.0 features it supports. For a conceptual introduction to the protocol itself — the publish/subscribe model, brokers, topics, and where MQTT fits versus other protocols — see the What is MQTT? guide and the rest of the MQTT guide.

TBMQ speaks MQTT 3.1, MQTT 3.1.1, and MQTT 5.0. A client declares its version in the CONNECT packet, and the broker adapts accordingly — MQTT 5.0-only behaviors such as reason codes and enhanced authentication apply only to 5.0 clients. All three versions are served on the same listeners — there is nothing to switch on per version.

For MQTT 3.1 clients specifically, the maximum accepted client identifier length is 1024 characters (MQTT_3_1_MAX_CLIENT_ID_LENGTH); 3.1.1 and 5.0 clients follow the spec’s own client-ID rules. See Client ID for how TBMQ handles uniqueness, client take-over, and broker-assigned identifiers.

TBMQ exposes four MQTT endpoints. The plaintext TCP and WebSocket listeners are enabled out of the box; the TLS variants ship disabled so you opt in after providing certificates.

Transport Default port Env var Enabled by default
MQTT over TCP 1883 LISTENER_TCP_BIND_PORT Yes
MQTT over TLS (MQTTS) 8883 LISTENER_SSL_BIND_PORT No (LISTENER_SSL_ENABLED=false)
MQTT over WebSocket 8084 LISTENER_WS_BIND_PORT Yes
MQTT over Secure WebSocket (WSS) 8085 LISTENER_WSS_BIND_PORT No (LISTENER_WSS_ENABLED=false)

Each listener rejects packets larger than 64 KB by default, set per listener via TCP_NETTY_MAX_PAYLOAD_SIZE, SSL_NETTY_MAX_PAYLOAD_SIZE, WS_NETTY_MAX_PAYLOAD_SIZE, and WSS_NETTY_MAX_PAYLOAD_SIZE (all 65536); raise the relevant one if your application publishes larger payloads. To turn on the encrypted listeners see MQTTS, and for the browser/WebSocket endpoints see MQTT over WebSocket.

TBMQ enforces — and lets you tune — a number of protocol-level behaviors. Each is controlled by an environment variable; the values below are the shipped defaults.

Behavior Default Env var
Max keep-alive (caps the value MQTT 5 clients request) 600 s MQTT_KEEP_ALIVE_MAX_KEEP_ALIVE_SEC
Topic aliases per connection (0 disables the feature) 10 MQTT_TOPIC_ALIAS_MAX
Max topic segments (0 = unlimited) 0 MQTT_TOPIC_MAX_SEGMENTS_COUNT
Allow subscribing to the root # wildcard enabled MQTT_SUBSCRIPTION_ROOT_MULTI_LVL_WILDCARD
Flow control / Receive Maximum enabled MQTT_FLOW_CONTROL_ENABLED
Receive Maximum applied to MQTT 3.x clients 65535 MQTT_FLOW_CONTROL_MQTT_3X_RECEIVE_MAX
Max session expiry interval 604800 s (1 week) MQTT_CLIENT_SESSION_EXPIRY_MAX_EXPIRY_INTERVAL

Two further limits come from your subscription rather than the configuration, and there is no environment variable for either. The session limit and the cluster-wide throughput quota are both sized by your plan and always enforced. Per-client publish rate limits are separate and off out of the box (MQTT_INCOMING_RATE_LIMITS_ENABLED). See Backpressure.

The full list of tunables lives in TBMQ configuration.

TBMQ implements the MQTT 5.0 feature set, including:

Feature Behavior in TBMQ
Reason codes Returned on CONNACK, PUBACK, SUBACK, DISCONNECT, and the other acknowledgement packets
User properties Preserved on the message and delivered to subscribers
Assigned client identifier The broker assigns a client identifier and returns it in CONNACK when a client connects without one
Session expiry interval Honored; capped at the max above (1 week by default)
Server keep alive The broker caps an MQTT 5 client’s requested keep-alive at the server maximum (600 s by default) and returns the enforced value in CONNACK
Message expiry interval Honored — messages still undelivered past the interval are discarded
Will delay interval Honored — a delayed Last Will is published after the interval, and cancelled if the session resumes first
Topic alias Enabled by default, up to 10 aliases per connection
Flow control (Receive Maximum) Enabled by default; also applied to MQTT 3.x clients
Maximum packet size The broker advertises the largest packet it accepts — the listener payload limit, 64 KB by default
Enhanced authentication (AUTH) SCRAM challenge/response — see SCRAM authentication
Shared subscriptions ROUND_ROBIN distribution — see Shared subscriptions
Request/response Off by default; when MQTT_RESPONSE_INFO is set, the broker advertises response information to clients that request it
Payload format indicator & content type Preserved and delivered with the message
Subscription options (No Local, Retain As Published, Retain Handling) Honored
Subscription identifier Honored and echoed in matching PUBLISH packets

An MQTT exchange is a sequence of control packets (CONNECT/CONNACK, PUBLISH and its QoS acknowledgements, SUBSCRIBE/SUBACK, PINGREQ/PINGRESP, DISCONNECT, and so on). MQTT 3.1.1 defines 14 packet types; MQTT 5.0 adds AUTH, for 15. TBMQ implements them all — including AUTH for SCRAM enhanced authentication and reason-coded DISCONNECT for MQTT 5.0 clients. For the packet-by-packet reference — fixed header, variable header, payload, and direction — see the MQTT packets guide.

TBMQ supports all three MQTT QoS levels — 0 (at most once), 1 (at least once), and 2 (exactly once). How TBMQ acknowledges and persists in-flight messages at each level is covered in Quality of Service.

Whether a client’s subscriptions and queued messages survive a disconnect depends on its session type — the MQTT 3.1.1 clean-session flag, or the MQTT 5.0 clean-start flag together with the session-expiry interval capped above. See Non-persistent and persistent sessions.

  • Encrypt traffic. Use MQTTS / WSS in production — see MQTTS.
  • Right-size QoS. Choose the lowest QoS that satisfies the use case; reserve QoS 2 for critical data, since its four-packet handshake carries the most overhead.
  • Lock down topics. Enforce publish/subscribe authorization through client credentials — see the security overview.
  • Constrain wildcards. Disable the root # subscription in production (see above) to prevent firehose or accidental data-leak subscriptions.
  • Scale horizontally. Distribute consumers with shared subscriptions and add nodes via clustering.