Skip to main content

Open navigation

Back to blog

MQTT 3.1.1 vs MQTT 5.0: Settings, Differences, and Tests

Explain every Mqttable New Client setting, then use publish, subscribe, and isolated wire tests to understand the problems MQTT 5 properties solve.

Author:
Mqttable Editorial
Published:
Hand-drawn comparison of MQTT 3.1.1 and MQTT 5.0 through a shared broker, with MQTT 5 message expiry, receive limits, and request-response controls.

Switch a client from MQTT 3.1.1 to 5.0 on the same Broker and port, and it may not connect any faster. What changes is how precisely it can express its needs: how long a disconnected session should survive, when a message becomes stale, how many reliable messages it can receive without acknowledging them, and whether a brief connection interruption should immediately notify other devices.

In this guide, V3 means MQTT 3.1.1 and V5 means MQTT 5.0. Mqttable also offers 3.1 for systems explicitly requiring the older protocol. The client, Broker, and listener policy must support the chosen version. TCP, TLS, WebSocket, and port numbers do not determine that version.

Differences at a glance

Scroll the table sideways to see all columns.

QuestionMQTT 3.1.1MQTT 5.0Why the change helps
Start fresh now, but retain a session after disconnect?One Clean Session flag combines both decisionsClean Start and Session Expiry are separateA fresh session can still have a defined recovery window
Are queued commands still useful when a device returns?No protocol Message Expiry propertyMessage Expiry IntervalPrevents stale commands being delivered after recovery
Should a brief interruption trigger a Will immediately?No Will Delay propertyWill Delay IntervalGives the same session time to recover before notification
How can a small receiver advertise its limits?Local windows and Broker policiesReceive Maximum and Maximum Packet SizeCommunicates outstanding-message and packet-size budgets
Why repeat a long Topic in every publication?Every PUBLISH carries its Topic nameTopic AliasA connection-local integer can replace a repeated Topic
Why did an operation fail?Limited feedback such as CONNACK return codes and SUBACKMore reason codes, optional Reason String, server DISCONNECTMakes failure location and meaning less ambiguous
How is a response matched to a request?Application-specific Topic and payload conventionsResponse Topic and Correlation DataCarries routing and correlation outside the business payload
How are self-echo and retained replay controlled?No equivalent standard subscription optionsNo Local, RAP, RH, Subscription IdentifierSupports bridges, replay control, and subscription attribution
Can authentication use several exchanges?Username/password and transport mechanismsAuthentication Method/Data and AUTHSupports challenge-response and in-connection reauthentication

These additions do not replace publish/subscribe. Topic, QoS, Retain, username/password, and basic Wills already exist in 3.1.1. MQTT 5 Appendix C summarizes new features and some intended uses. The device, bridge, and command examples here are engineering interpretations, not a history of standards-committee decisions.

New Client: identity, version, and credentials

Choose a Broker in Connections, then open New Client / Add client. The Broker row identifies the endpoint this client belongs to. Host, Port, transport, TLS, and certificates are Broker settings, not new MQTT 5 properties. The laboratory endpoints below bind only to loopback; use your organization's endpoint and trusted credentials for real deployments.

Mqttable New Client: Keep the same ID; V3.1.1 selected; Keep Alive seconds; Clean Session in V3.
  1. Keep the same ID; 2. V3.1.1 selected; 3. Keep Alive seconds; 4. Clean Session in V3.
  2. Keep the same ID
  3. V3.1.1 selected
  4. Keep Alive seconds
  5. Clean Session in V3
Mqttable MQTT 5 New Client form distinguishes display name, stable Client ID, credential, protocol version, and authentication policy.

Name stays inside the app, Client ID identifies the session, credentials do not encrypt transport, and the version is independent of the port.

  1. Name stays in app
  2. Stable session ID
  3. Credentials, not TLS
  4. Version, not port
  5. Match listener policy

Name, Client ID, and their generation buttons

Scroll the table sideways to see all columns.

SettingMeaning and usageVersion relationship
NameA Mqttable display name, limited to 255 UTF-8 bytes. A name such as Temperature Reader is not transmitted as the MQTT Client IDTool feature, unchanged between versions
Generate a new nameGenerates a display name; it does not create a Broker account or change a connected device's identityTool feature
Client IDThe identity sent in CONNECT. The current form accepts bounded UTF-8 strings, subject to the Broker's own length and character policyShared protocol feature; a tool input limit is not universal Broker support
Generate Client IDCreates a new test identity to reduce collisions. Do not regenerate it when you need an existing sessionTool feature

Two connections using the same Client ID on the same Broker can cause the newer connection to take over the older one. Session recovery needs a stable Client ID. Disabling Clean Start while generating a different ID each time cannot recover the old session. MQTT 5 can also return a server-assigned identity; the generation button does not imply that it uses that mechanism.

MQTT version and Authentication Method

Scroll the table sideways to see all columns.

OptionPurposeRequirements and limits
5.0Uses MQTT 5 properties, reason codes, and subscription optionsThe listener must accept 5.0. There is no separate universal V5 port
3.1.1Interoperates with many existing devices and librariesCONNECT Protocol Level is 4, not the UI version string
3.1Supports systems explicitly requiring the older protocolProtocol Level is 3; this guide is not a second tutorial for that version
NoneSends no passwordThe Broker can still authenticate through username, certificates, network identity, or another policy. It does not force anonymous access
PasswordSends the credentials required by the BrokerAlready supported in 3.1.1; a password does not encrypt plain TCP
JWTUses a token in the Password fieldThe Broker validates it. It normally travels as ordinary CONNECT Password, not a V5-only mechanism
SCRAM-SHA-1/256/512Performs MQTT 5 challenge-response authentication using AUTH exchangesBoth endpoints must support the same method. SHA-256 is tested here; the other methods are explained, not claimed as tested

Mqttable currently exposes this selector under 5.0. Under 3.x it is hidden, while Username and Password remain available. At protocol level, a Broker supporting JWT can accept it in a 3.1.1 Password field. The location of JWT Tools in the V5 form does not make JWT a V5 feature.

The V5 addition is enhanced authentication, including a method, authentication data, and AUTH packets. Challenge-response need not transmit the original secret as CONNECT Password, and the protocol permits reauthentication within an existing connection. SCRAM does not replace TLS, and protocol support does not prove Mqttable has a button for initiating reauthentication. See the authentication guide and EMQX SCRAM configuration.

Authentication reference distinguishes None, Password, JWT, and MQTT 5 SCRAM, with numbered pointers to actual rules.

Password and JWT are not V5-only; the SCRAM method must match at both endpoints.

  1. Match listener policy
  2. No password sent
  3. Ordinary credentials
  4. Token in Password
  5. V5 AUTH exchange

Username, Password, and Saved SecretRef

Username and Password start empty. Enter the credentials required by the policy when using Password or SCRAM. None sends no password, even if an old saved value exists. The Password field is bounded by MQTT's two-byte length, at most 65,535 bytes; this is not a suggested password length and does not override provider restrictions.

  • Raw password directly enters the credential. Show/hide only changes visibility; it does not change authentication, encryption, or permissions.
  • Saved SecretRef selects a stored MQTT password in Credentials. The reference is not the password sent to the Broker and is not a V5 property; the Runtime resolves it when connecting. Repair a missing reference rather than sending its text as a password.
  • Key/Value and Add/Remove belong to CONNECT User Properties, discussed below. They are not extra password fields.

Only synthetic laboratory credentials are used here. Screenshots do not expose passwords, signing keys, or usable token text. Never place production credentials in User Properties, Topics, payloads, screenshots, or an article.

Mqttable Saved SecretRef selects the task-owned Password Secret created through Credentials, without exposing the password.

The Runtime resolves the reference; it is not an MQTT property or a password string transmitted to the Broker.

  1. Direct credential entry
  2. Reuse a saved password
  3. Own laboratory reference
  4. Policy stays separate

JWT Tools: algorithms, keys, claims, Encode, and Preview

JWT Tools is a Mqttable utility. None of these controls is an MQTT packet field.

Scroll the table sideways to see all columns.

Tool settingMeaning and usage
AlgorithmHS256 and RS256 are currently offered. Match the Broker's verification policy; successful generation does not prove the Broker accepts the token
SecretThe shared signing secret for HS256; both sides must agree. It is not an automatically generated MQTT password
Private Key (PEM)RS256 signs with a PEM private key; the Broker normally holds the corresponding public key. Do not publish the private key
Claims Key/ValueDefines token claims. Add/Remove changes this token, not the Broker's validation policy
iatIssued-at time. The tool's hint uses the current time; Unix timestamp units are seconds
expExpiry time. The current tool's default example is now plus 3,600 seconds, unrelated to MQTT session or message expiry
EncodeOpens the generation view for algorithm, key, and claims
Generate & FillGenerates a token and fills Password. It does not prove authentication or publish permission
PreviewParses Header, Payload, and time information from Password; it does not verify the signature
Open in JWT DebuggerOpens the separate debugger. Use its verification result, not successful Preview parsing, when checking a signature

Whether Username, Client ID, subject, or another claim must match is a Broker policy. MQTT does not require them to be the same string.

JWT Encode shows HS256, masked signing secret and token, claims, expiry, and Generate and Fill.

The synthetic token is generated and masked; Broker acceptance is not implied.

  1. Signing algorithm
  2. HS256 signing secret
  3. Application claims
  4. Token expiry only
  5. Fill, not connect
JWT Tools selects RS256 with a deliberately blank PEM input and no exposed key or token.

Changing algorithm does not generate a key or verify the existing token.

  1. Match RS256 public key
  2. PEM signing private key
  3. Preview does not verify

Sessions, keepalive, and connection properties

Mqttable New Client: Fresh or resumed?; Retention after loss; Liveness interval; Off sends zero; Optional response info.
  1. Fresh or resumed?; 2. Retention after loss; 3. Liveness interval; 4. Off sends zero; 5. Optional response info.
  2. Fresh or resumed?
  3. Retention after loss
  4. Liveness interval
  5. Off sends zero
  6. Optional response info

Clean Session and Clean Start do not mean automatic reconnect

With MQTT 3.1.1 Clean Session=1, an old session is discarded and the new session is not retained after disconnect. With 0, the Broker attempts recovery and retains state afterward. State includes subscriptions and incomplete QoS 1/2 delivery. Retained messages are not part of an individual client's session.

In MQTT 5, Clean Start only decides whether to discard an old session at connection time. Session Expiry Interval controls retention after disconnect. The current New Client defaults to the cleanup flag enabled.

Scroll the table sideways to see all columns.

MQTT 5 combinationAt connection timeAfter disconnect
Clean Start on, Expiry 0Start a fresh sessionEnd the session, similar to V3 Clean Session on
Clean Start on, Expiry 60Discard old state and create a new sessionRetain the new session for 60 seconds
Clean Start off, Expiry 60Resume a session if one exists, otherwise create oneRetain it for 60 seconds
Clean Start off, Expiry 0Can still request an existing sessionEnd the session when this connection closes

Why separate the controls? The V3 flag combines "where should this connection start?" and "how long should later state survive?" It cannot express "start from scratch now, but retain this new session for one minute." V5 permits a recovery window without indefinitely retaining sessions for devices that never return.

Session Expiry Interval

Units are seconds, with a protocol range of 0 to 4,294,967,295. Omission defaults to 0. Zero ends the session after disconnect; the maximum means no time-based expiry at protocol level, still subject to Broker resource and administrative policies. The current New Client defaults to 0 and omits the property.

For offline QoS 1/2 recovery, use a stable Client ID, Clean Start off, and a deliberate positive interval. The experiment uses a two-second interval and checks CONNACK Session Present after a longer observation window. A restored UI subscription list is insufficient: Mqttable can restore configured subscriptions automatically. Check Session Present and queued messages to distinguish Broker recovery from local resubscription.

Keep Alive

Units are seconds, range 0 to 65,535, with a current product default of 300. Zero disables MQTT Keep Alive. When there are no other MQTT control packets to send, PINGREQ/PINGRESP checks connection liveness; the Broker handles timeout under the protocol. It does not require a business message every interval, and is not a subscription or message lifetime.

Keep Alive exists in both versions. V5 adds Server Keep Alive, allowing CONNACK to state the value the client should use. Shorter intervals generally detect disconnection sooner but add traffic and device wakeups. Choose based on power, connectivity, and Broker policy rather than a universal best number.

Request Problem Info

The wire value is 0 or 1, with a specification default of 1 when omitted. In the locally fixed Mqttable, the default unchecked control explicitly sends 0; checked sends 1. An absent or nil field remains omitted.

One allows Reason String and User Properties in packets where permitted, but does not require the Broker to provide them. Zero restricts some packets' additional information. It does not disable reason codes or prohibit information permitted in PUBLISH, CONNACK, or DISCONNECT. Reason String is not a stable machine-readable interface.

V5 makes diagnosis more useful while letting small clients express a budget for extra strings and metadata. This control is not a sensitive-data filter.

Request Response Info

The value is 0 or 1, defaulting to zero when absent. The current default is off, which omits the property. Enabling it asks for Response Information in CONNACK, but the Broker may still omit it.

It can help a requester construct response Topics alongside the PUBLISH Response Topic and Correlation Data properties. It does not subscribe to a response Topic, turn every publish into a request, or make the Broker execute a response. V3 applications must arrange these conventions outside those standard fields.

Quotas and User Properties: advertise the receiving budget

Mqttable New Client: QoS 1/2 window; Inbound alias budget; Whole-packet bytes.
  1. QoS 1/2 window; 2. Inbound alias budget; 3. Whole-packet bytes.
  2. QoS 1/2 window
  3. Inbound alias budget
  4. Whole-packet bytes

Receive Max: outstanding QoS 1/2 messages

The range is 1 to 65,535; zero is invalid. Omission defaults to 65,535. The initial Mqttable field is empty: its 65535 placeholder does not mean the property is already being sent.

In CONNECT, the client advertises the maximum outstanding QoS 1/2 PUBLISH messages it accepts from the Broker. The CONNACK value limits the opposite direction. It does not limit QoS 0 or specify messages per second.

V3 implementations can configure local in-flight limits and Broker policies, but cannot advertise this standard field to each other. V5 lets the sender pause new reliable messages at the receiver's limit. The auxiliary test receiver deliberately withholds PUBACK: with a window of two it does not receive all four messages before acknowledging, and one acknowledgement releases another message.

Maximum Packet Size includes the whole MQTT packet

The property is a positive four-byte integer; zero is invalid. Omission adds no receiver size restriction beyond protocol encoding, implementation, and resource limits. Mqttable starts with an empty field; entering 0 means omit the property, not send an illegal zero.

CONNECT states the client's receiving limit, including Topic, Packet Identifier, properties, and payload. CONNACK states the Broker's receiving limit. A 100-byte payload is not necessarily a 100-byte PUBLISH.

This gives small devices a defined memory budget before an oversized message is transmitted. The Broker must not forward a packet larger than the client's limit. A sender's PUBACK does not prove a constrained subscriber received it. In the test, a 128-byte limit prevented forwarding a 512-byte payload; successful small messages before and after were the controls.

Topic Alias Max: how many mappings the peer may use

The range is 0 to 65,535, default zero if absent. The initial field is empty; zero permits no aliases. CONNECT advertises accepted Broker-to-client aliases. A publishing client's client-to-Broker allowance comes from CONNACK.

Topic Alias is a separate PUBLISH property, starting at 1 and never exceeding the peer's limit. A real Topic first establishes the mapping; subsequent packets on that connection can omit the repeated Topic name. Mappings do not survive reconnection and are not session state. Setting Topic Alias Max to ten does not automatically create ten mappings.

The V5 feature reduces repeated long-Topic overhead. Independent limits prevent saved bandwidth turning into an unbounded mapping-memory cost. The experiment checks both directions rather than treating one UI number as sufficient evidence.

User Properties are connection metadata, not global message labels

User Properties are repeatable UTF-8 Key/Value pairs. Each uses a two-byte length field; repeated keys are permitted by the protocol. The current Client form supports 100 pairs, while the ordinary connection implementation requires non-empty Key and Value. This count is a product limit, not an MQTT limit.

Add/Remove edits this CONNECT's metadata, such as device-class=sensor or firmware=lab. The application or Broker implementation defines their meaning. CONNECT properties are not automatically forwarded to subscribers or copied onto future PUBLISH packets. Set message metadata separately in the publishing panel.

V5 supplies a standard container for extension metadata without placing everything in a Topic or business payload. It does not define every key or make untrusted metadata an authenticated authorization claim.

Mqttable CONNECT User Properties contain an application-defined device-class key and sensor value with add/remove controls.

CONNECT metadata is separate from PUBLISH metadata; the current form permits 100 pairs.

  1. Application-defined key
  2. Only this CONNECT
  3. Up to 100 pairs

Last Will: shared basics plus V5 timing and message metadata

A Will is registered with the Broker during CONNECT, not set whenever Publish is pressed. A normal DISCONNECT should not publish it; abnormal connection loss and other triggers follow protocol and Broker behavior.

Mqttable New Client: Will Topic Name; Offline payload; JSON utility only; Will delivery QoS; Retained status.
  1. Will Topic Name; 2. Offline payload; 3. JSON utility only; 4. Will delivery QoS; 5. Retained status.
  2. Will Topic Name
  3. Offline payload
  4. JSON utility only
  5. Will delivery QoS
  6. Retained status

Topic, Payload, QoS, Retain, and JSON tools

Scroll the table sideways to see all columns.

SettingDefault, limits, and useNew in V5?
Last-Will TopicInitially empty. A valid Topic Name without + or #; no Topic means no registered WillNo
Last-Will PayloadInitially empty. Current form limit: 65,535 UTF-8 bytes. For example {"status":"offline"}; an empty payload also has meaningNo
QoSDefault 0, options 0/1/2. Governs the Broker's Will publication, subject to subscription and Broker capabilityNo
Retain Last-Will MessageDefault off. On can preserve an offline status for later subscribersNo
Edit JSONEdits the Will draft using the utility, not its QoS or protocol versionTool feature
FormatFormats valid JSON. It does not mean the Broker requires JSON payloadsTool feature
Open in JSONOpens a JSON workspace for the draft, not an already-published WillTool feature

QoS 1 can deliver duplicates. MQTT QoS 2 does not itself guarantee exactly one database write. Retain stores the last retained message for a Topic, not all history, and does not depend on a particular subscriber's session surviving.

Will Delay, Message Expiry, and additional properties

Mqttable New Client: Wait before Will; TTL after publish; Describe the payload; Reply routing; Correlation bytes.
  1. Wait before Will; 2. TTL after publish; 3. Describe the payload; 4. Reply routing; 5. Correlation bytes.
  2. Wait before Will
  3. TTL after publish
  4. Describe the payload
  5. Reply routing
  6. Correlation bytes

Scroll the table sideways to see all columns.

V5 settingDefault or omitted behaviorUsage and purpose
Will Delay IntervalSeconds, 0 to 4,294,967,295, default zero; the product omits zeroProvides a brief interruption window. Publish when the delay elapses or the session ends, whichever is earlier; resuming the same session suppresses the pending Will
Message Expiry IntervalSeconds, 0 to 4,294,967,295; omission means no protocol TTL. The current product omits 0, so it cannot express the protocol's immediate-expiry zero hereLimits the Will's lifetime after publication, not the delay measured from connection loss
Content TypeInitially empty, a MIME type agreed by applications, such as application/json; no payload conversionHelps the receiver interpret content; declaring JSON is not validation
Response TopicInitially empty; a valid Topic Name without wildcardsSupplies response routing when an application uses that pattern; no automatic reply or subscription
Correlation DataInitially empty; binary at protocol level. The current text input sends bytes such as request-7, not automatic Base64 decodingAssociates a response with its request; not a Client ID, sort key, or universal deduplication key

The V5 specification also permits Will Payload Format Indicator and Will User Properties. The current New Client Will area has no independent controls for them. Do not label the publish-panel UTF-8 switch as a Will control, or CONNECT User Properties as Will metadata.

Will Delay must be considered with Session Expiry. If Expiry is zero, the session ends at disconnection, so a ten-second Will Delay alone cannot promise a ten-second notification grace period. The experiment retains the session longer than the delay and separately checks reconnection within that interval and failure to reconnect.

Test Connection, Cancel, and Connect have different outcomes

  • Test Connection temporarily checks the current protocol and credentials. It does not save a new Client or establish a persistent connection. The current test registers no Will, publishes nothing, subscribes to nothing, and does not automatically reconnect.
  • Cancel leaves the unsaved form. It does not undo earlier Broker-side connection or testing effects.
  • Connect saves configuration and starts a real connection. Connected proves connection establishment, not subscription approval or message delivery.

Test Connection uses the real Client ID. It can take over an existing connection, trigger that connection's Will, or affect sessions and queued messages. A passed test does not verify publish, subscribe, Will permissions, or all quota settings. Broker transport testing and Client authentication testing are different entry points.

Publishing: attach V5 metadata to the specific PUBLISH

Mqttable sends from a selected MQTT 3.1.1 client with Topic, text payload, QoS 1, and Retain controls.

Client, Topic, Payload, QoS, and Retain exist in both versions. This is an unsent configuration example.

  1. Sending connection
  2. Topic Name only
  3. Application bytes
  4. Delivery QoS
  5. Last retained value

Client selects the sending connection. Topic is a Topic Name without subscription wildcards. Payload is application content; MQTT does not require JSON. QoS selects 0/1/2, and Retain controls the Topic's retained message. All exist in 3.1.1.

Mqttable MQTT 5 publication properties: application/json, message expiry 30 seconds, UTF-8, and message User Properties.

These properties belong to this PUBLISH. Content Type and UTF-8 do not replace business validation.

  1. Content description
  2. Message TTL seconds
  3. UTF-8, not JSON
  4. Per-message metadata
Mqttable MQTT 5 publish form with Response Topic, Correlation Data, Topic Alias, and chosen sending client.

The reply route and correlation bytes are application conventions. An alias must stay within the peer allowance.

  1. Subscribe for replies
  2. Match the request
  3. Connection-local alias
  4. V5 sending client

Scroll the table sideways to see all columns.

Publish propertyValues and omitted behaviorV5 purpose and limits
Content TypeOptional UTF-8 string, for example application/jsonDescribes content, without automatically decoding, converting, or validating its business structure
Payload Format IndicatorZero or omission means unspecified bytes; one means UTF-8 character data. The current switch is labeled UTF-8Describes encoding, not JSON validity or the utility's Base64 input mode
Message ExpiryFour-byte seconds value. Omission means no protocol TTL; the protocol's zero means immediate expiryLimits messages not yet forwarded and retained storage; does not cancel work already underway in a receiving application
Response TopicOptional valid Topic Name without wildcardsTells the responder where to reply. Subscribe before sending the request
Correlation DataOptional binary data, sent as bytes by the current text inputThe responder returns the original bytes under application policy to distinguish concurrent requests
Topic AliasFrom 1 up to the peer's advertised CONNACK allowance; zero is illegal. Omission uses the normal TopicMappings are connection-local. A protocol example with an empty Topic does not prove every UI can submit an empty Topic
User PropertiesRepeatable Key/Value; current publish form limit is 100 pairsApplication metadata forwarded with the message, separate from CONNECT properties

Why not continue putting everything in JSON? V3 applications can implement TTL, request IDs, and content types, but each needs its own payload convention. A Broker generally cannot enforce protocol expiry or routing using an arbitrary business convention. V5 standardizes the metadata container while leaving payload design open.

Message Expiry does not replace application-side timestamp checks. Topic Alias does not guarantee every connection saves bandwidth; inspect whether actual PUBLISH packets established and reused mappings.

Subscriptions: control what comes back and how

Mqttable MQTT 3.1.1 subscription form with Topic Filter, fixed subscriber identity, and requested QoS.

V3 has Topic Filter and QoS but no standard MQTT 5 subscription option bits. Alert Monitor is separate.

  1. Wildcard Topic Filter
  2. Subscriber identity
  3. Read the SUBACK grant
Mqttable MQTT 5 subscription options: QoS 1, No Local, Retain as Published, Retain Handling, and Subscription Identifier 7.

Change one option at a time when testing. Subscription Identifier reports matching subscriptions, not unique message identity.

  1. Maximum requested QoS
  2. Suppress self echo
  3. Preserve Retain flag
  4. Replay only if new
  5. Which subscription?

Client selects the subscriber. A Topic Filter can use + for one level and # for subsequent levels. QoS requests the highest delivery level; read SUBACK for the grant. The following V5 options are not part of the standard 3.1.1 SUBSCRIBE format.

Scroll the table sideways to see all columns.

SettingDefaults and valuesWhy V5 adds it
No LocalDefault off, bit 0/1; on suppresses messages originating from this clientReduces self-echo in bridges and publish/subscribe clients; does not block other publishers or disable local networking
Retain as Published (RAP)Default off; on preserves the publication's Retain flag, while off follows normal live-forwarding rulesHelps bridges preserve retained semantics; it does not decide whether stored retained messages are replayed on subscribing
Retain Handling (RH)Default 0; zero requests retained replay on subscribe, one only for a new subscription, two no subscription-triggered retained replayAvoids repeatedly processing old state; two does not block future live messages
Subscription IdentifierOptional, 1 to 268,435,455; zero is illegalIdentifies matching subscriptions on received PUBLISH packets, especially overlapping filters; not a Client ID or unique message ID

For RH one, "new" means the Broker's subscription state, not that the user just opened the Client. If a tool unsubscribes before subscribing again, that is not an update to an existing subscription. The experiment directly repeats SUBSCRIBE through an auxiliary client to distinguish RH zero, one, and two.

Shared subscriptions standardize an existing Broker extension

Use $share/group/TopicFilter, for example $share/version-workers/versions/shared. For each matching message, the Broker chooses a subscriber in that group, providing work distribution. It does not promise strict round-robin, even distribution, or exactly-once business processing. The group and filter must satisfy shared-subscription syntax, and No Local must not be set to one for a shared subscription.

Mqttable shared-subscription filter with group name version-workers and No Local disabled.

The group shares work; it does not promise equal distribution. Some Brokers also support this extension under V3.

  1. Group and Topic Filter
  2. Must be off for shared
  3. One group participant

MQTT 5 standardizes shared subscriptions, but some Brokers already offer them with 3.1.1. Do not claim V3 systems cannot distribute work; distinguish the standard from Broker extensions. Respect a CONNACK Shared Subscription Available declaration.

Verify with real packets, not configuration alone

The tests use task-owned Mosquitto, EMQX, and the locally fixed Mqttable source Runtime on loopback. Auxiliary protocol clients handle steps the UI cannot precisely control, including delayed PUBACK and repeated SUBSCRIBE. Those results are not attributed to Mqttable button clicks. Packet capture is restricted to this laboratory's ports. The screenshot endpoint 22932 is a loopback recording proxy forwarding to Mosquitto on 22931; readers can connect directly to 22931. That recording proxy is not an MQTT 5 requirement.

A minimal reproducible laboratory

With Mosquitto already installed on macOS or Linux, create a private, separate experiment directory. These commands do not overwrite a configuration. Port 22931 must be free; stop and choose another loopback port if it is occupied.

bash
LAB_DIR="$(mktemp -d)"
printf '%s\n' "$LAB_DIR"
cat > "$LAB_DIR/mosquitto.conf" <<'CONF'
listener 22931 127.0.0.1
allow_anonymous true
persistence false
CONF
mosquitto -c "$LAB_DIR/mosquitto.conf"

Anonymous access is for this local experiment, not public deployment. In Mqttable, create Broker mqtt://127.0.0.1:22931, then two distinct Client IDs for 3.1.1 and 5.0. Start with QoS 1 and Retain off, and wait for subscription confirmation before publishing.

Session recovery and message expiry

  1. Disable Clean Session for V3. For V5, disable Clean Start and use a positive Session Expiry. Keep the Client ID stable.
  2. Subscribe to versions/session, disconnect the subscriber normally, and publish QoS 1 from another connection.
  3. Reconnect within the retention window. Check CONNACK Session Present and the queued message, not just the local subscription list.
  4. Disconnect V5 again and reconnect after expiry to check that the old session has ended.
  5. With a recoverable session, publish a short-TTL message while offline, wait beyond TTL, and reconnect. Then send a fresh message as the positive control.

In this source snapshot, Trace records contain ack_flags, while the inspector reads a different Session Present field name and may not display it. A missing UI row is not zero. Recovery is verified from actual packet flags and the low bit of the Trace record; the CONNACK screenshot below illustrates acceptance and receiving limits only.

Mqttable inspects a real MQTT 5 CONNACK with success code 0x00, Topic Alias Maximum 10, Maximum Packet Size 65536, and Receive Maximum 20.

These CONNACK limits describe what the Broker receives. Session Present is verified from actual flags, not a missing inspector row.

  1. Connection, not delivery
  2. Zero means accepted
  3. Broker alias allowance
  4. Broker receiving limits

Actual results and waiting windows appear in the verification table. A screenshot containing no messages does not prove expiry works; negative observations require timing and a successful delivery control.

Reproduce message expiry without writing a client

These commands were tested with this run's Mosquitto 2.1.2. The first subscription creates a session and exits after the expected one-second timeout. Exit code 27 is not an authentication error; stop for other failures. A two-second message TTL followed by a five-second wait means recovery should not deliver stale-command.

bash
# Keep a session for 30 seconds; exit 27 is the expected one-second timeout.
mosquitto_sub -h 127.0.0.1 -p 22931 -V mqttv5 \
  -i article-cli-expiry -c -x 30 -q 1 -t versions/cli-expiry -W 1 -v \
  || [ "$?" -eq 27 ]
mosquitto_pub -h 127.0.0.1 -p 22931 -V mqttv5 -q 1 \
  -t versions/cli-expiry -m stale-command \
  -D PUBLISH message-expiry-interval 2
sleep 5
mosquitto_sub -h 127.0.0.1 -p 22931 -V mqttv5 \
  -i article-cli-expiry -c -x 30 -q 1 -t versions/cli-expiry -W 1 -v \
  || [ "$?" -eq 27 ]

Positive control: keep the following subscription running and publish fresh-command from a second terminal. It should arrive. An empty one-second observation by itself is not proof of expiry.

bash
mosquitto_sub -h 127.0.0.1 -p 22931 -V mqttv5 \
  -i article-cli-expiry -c -x 30 -q 1 -t versions/cli-expiry -C 1 -W 4 -v
bash
mosquitto_pub -h 127.0.0.1 -p 22931 -V mqttv5 -q 1 \
  -t versions/cli-expiry -m fresh-command \
  -D PUBLISH message-expiry-interval 2

Will delay and request/response

A separate observer subscribes to versions/will/#. The observed client uses a positive Session Expiry longer than Will Delay. A normal Disconnect sends no Will; abnormal loss followed by a wait beyond the delay produces one. Recovering the same session within the delay, with the same Client ID and Clean Start off, suppresses it. With Message Expiry on a retained Will, a later subscriber must not receive that expired state; a fresh publication verifies the path still works.

For request/response, subscribe the requester to versions/reply first. Publish a request with that Response Topic and Correlation Data request-7. The responder subscribes to versions/request, replies to the specified Topic, and returns the same correlation bytes. The Broker does not execute the business operation, and PUBACK is not the business response.

Mqttable receives an actual reply payload 21.5 with Correlation Data request-7, Subscription Identifier 7, and inbound Topic Alias 1.

The received PUBLISH carries the correlation bytes and matching subscription ID. PUBACK alone would not prove this reception.

  1. Actual application reply
  2. Same request-7 bytes
  3. Matched subscription 7
  4. Inbound connection alias

Quotas, aliases, and subscription options

The auxiliary flow-control receiver advertises Receive Maximum two and withholds PUBACK, then acknowledges one message to release budget. The size test advertises 128 bytes, publishes a small message, a 512-byte payload, and another small message. A sender's PUBACK is not proof of subscriber receipt.

The alias test checks both CONNECT and CONNACK budgets, the initial Topic mapping, and subsequent PUBLISH packets. Reconnection requires a new mapping.

Change subscription options individually: No Local compares self-publishing with a different connection; RAP compares the Retain bit on the same live retained publication; RH compares first and repeated subscriptions; Subscription Identifier is checked in received PUBLISH. Shared subscriptions require correct combined message identity and count, not a forced fifty-fifty split.

Results from this run

Scroll the table sideways to see all columns.

ScenarioResultEvidence boundary
Session recoveryV3/V5 Session Present true and queued QoS 1 deliveryAuxiliary clients; fixed IDs
Session expiryV5 expiry 2 s; after 5 s disconnected, Session Present falseNot inferred from resubscription
Queued/retained expiryTwo-second stale messages absent; fresh controls deliveredObservation beyond TTL
Will publication/suppressionNormal close: none; abnormal loss: Will; same-session recovery suppresses itWill Delay 1/2 s; session expiry 20 s
Will message expiryWill observed; later subscriber does not receive expired retained statusFresh state control
Request/responseReply 21.5 returns request-7 correlation bytesAuxiliary and managed Mqttable loops verified separately
Receive MaximumWindow 2: two before ACK; one ACK releases one moreAuxiliary receiver withholds PUBACK
Maximum Packet Size128-byte limit prevents 512-byte payload forwarding; small controls arriveSender PUBACK is not receipt
Bidirectional aliasesBroker budget 10; client budget 2; mappings reusedSeparate directional budgets
No Local / RAP / RHSelf-echo suppressed; RAP differs; RH new/repeated behavior verifiedPositive controls; repeated direct SUBSCRIBE
Subscription ID/shared subscriptionsIdentifier 7 received; six jobs distributed without duplicatesNo fairness or business exactly-once claim
Server disconnectSame-ID takeover returns V5 DISCONNECT 0x8EActual Broker response
SCRAM-SHA-256Managed Mqttable connected; actual AUTH/AUTH/CONNACK 0x00Credentials + SecretRef + Compact MCP; not raw-submit acceptance
CLI expiry reproductionExpected timeout exit 27; no stale command, fresh-command receivedPublished CLI arguments tested

SCRAM and rejection reasons

The SCRAM-SHA-256 experiment uses a separate EMQX 6.0.0 instance, a scram:built_in_database authenticator, and a synthetic user. Mqttable selects the same method. The tested connection uses a synthetic password stored through Credentials and a SecretRef created through Compact MCP; raw-password form submission is not claimed as accepted. Inspect real AUTH/CONNACK rather than treating a selected dropdown option as authentication success. This does not validate SHA-1, SHA-512, or reauthentication within an existing connection.

Mqttable Add client selects MQTT 5 and SCRAM-SHA-256 for a loopback EMQX Broker; the synthetic password remains masked.

Both endpoints must use the same SCRAM method. A configured method is not proof of a successful AUTH exchange.

  1. AUTH needs MQTT 5
  2. Match SHA-256 policy
  3. Synthetic lab user
  4. Masked local credential
Real Mqttable SCRAM-SHA-256 Trace contains CONNECT, received AUTH challenge, sent AUTH response, and successful CONNACK without revealing authentication data.

Read timestamps in chronological order: CONNECT, AUTH challenge, AUTH response, CONNACK. This proves connection authentication, not message permissions.

  1. Client starts CONNECT
  2. Broker challenge
  3. Client response
  4. Connection accepted

For rejection, distinguish MQTT 3.1.1 CONNACK return codes from MQTT 5 reason codes; exact values follow the Broker's observed policy. Duplicate Client ID takeover can also produce a server DISCONNECT 0x8E under V5. Reason String is optional: do not fabricate one when the Broker omits it. Use the error-code reference for meanings.

MQTT 5 features that are not New Client input fields

Scroll the table sideways to see all columns.

CapabilityProblem addressedBoundary in this guide
Reason codes and Reason StringMore explicit publish, subscribe, and disconnect outcomesNot all reason codes are errors; diagnostic text is not a stable API
Server DISCONNECTLets the Broker explain why it closes a connectionShows actual takeover, not invented refusal reasons
CONNACK Maximum QoS and Retain/Wildcard/Subscription Identifier/Shared Subscription AvailableAdvertises optional Broker capabilities before unsupported operationsBroker response properties, not another set of client toggles; absent optional attributes are not invented
Server Keep AliveLets the Broker state the desired keepalive intervalNot another client input field
Assigned Client IdentifierReturns a Broker-generated identity for later useThe Client ID generation button is not claimed to use it
Server ReferenceIndicates an alternative server with applicable CONNACK/DISCONNECT reasonsDoes not prove Mqttable automatically migrates a connection; redirect behavior is not tested here
AUTH and reauthenticationSupports challenge-response and authentication within a connectionConnection-phase SCRAM is tested; no claim of an initiating reauthentication UI

Migrating from 3.1.1 to 5.0

Confirm the Broker and device SDK support V5, then use a non-production identity for a complete message loop. Changing a version string does not preserve every behavioral assumption.

  • For V3 Clean Session on behavior, use V5 Clean Start on and Session Expiry zero.
  • For offline recovery, retain the Client ID and choose Clean Start off plus a deliberate positive interval. 4,294,967,295 means no protocol time-based expiry, not eternal survival through every Broker failure.
  • For time-sensitive commands, define Message Expiry and application timestamp checks. For noisy connection-status notifications, consider Will Delay with sufficient Session Expiry.
  • For constrained receivers, configure Receive Maximum and Maximum Packet Size. Their direction matters; they are not a publishing-rate control.
  • Introduce Response Topic, Correlation Data, No Local, RAP, RH, and Subscription Identifier when request/response, bridges, or overlapping subscriptions need them.

Choosing 3.1.1 does not make a system unreliable. Choosing 5.0 does not automatically repair authentication, reconnection, duplicate processing, or stale business data. Express requirements in configuration, then inspect CONNECT/CONNACK, SUBACK, PUBLISH, and real reception.

Common questions

Does V5 require a different port? No. A listener decides which versions it accepts; a port and MQTT protocol version are different configuration layers.

Are QoS 2, Retain, and JWT new V5 features? No. QoS 2 and Retain exist in V3, and JWT can be ordinary MQTT Password material. V5 adds standard properties, enhanced authentication, and associated behavior.

Can Session Expiry, Message Expiry, Will Delay, and JWT exp replace each other? No. They govern disconnected sessions, message usefulness, Will publication timing, and token validity respectively.

Why is Response Information missing despite Request Response Info? The specification permits the Broker to omit it; response routing and correlation still require application agreement.

Does a restored subscription list prove session recovery? No. A client may have resubscribed. Inspect Session Present and queued delivery to distinguish local configuration from Broker state.

Continue with connection settings, publish and subscribe, Trace, and PCAP analysis. TLS, alerts, and scheduled messages have their own configuration boundaries rather than being MQTT-version differences.