Shopfloor

MQTT QoS, retained messages, and sessions, explained

The three MQTT features that decide whether your telemetry is lossy, stale, or exactly-once — and when each setting is correct.

MQTT is easy to start and easy to misconfigure, because the defaults quietly choose "at most once, no history, forget me on disconnect" — reasonable for sensor streams, wrong for commands and state. Three mechanisms control delivery behavior: quality of service, retained messages, and session persistence.

FIG. 02From machine to data
Connect. Transport. Record. A gateway, a switch and a recorder: separate jobs along a connected machine’s data path. The equipment arrangement is illustrative.

QoS 0, 1, 2: the delivery contract

  • QoS 0 (at most once) — fire and forget. Fastest, no broker acknowledgment. Correct for high-rate telemetry where the next reading supersedes the last (temperatures, vibration streams).
  • QoS 1 (at least once) — broker acknowledges; the publisher retries until it hears back, so subscribers may receive duplicates. Correct for events that must arrive but tolerate repeats (alarms, counters with idempotent handling).
  • QoS 2 (exactly once) — four-step handshake, no duplicates, highest overhead. Correct for billing-grade events and commands where a duplicate would double-actuate. Rarely needed on the plant floor; reach for it deliberately, not by default.

Note the subtlety: QoS is negotiated per hop (publisher→broker, broker→subscriber) and downgraded to the subscription's maximum. Publishing at QoS 2 to a QoS 0 subscriber still delivers at most once.

Retained messages: state on subscribe

A retained message is stored by the broker and delivered immediately to every new subscriber — the topic's "last known value." This is how dashboards show current state without waiting for the next publish cycle, and it is the mechanism Sparkplug B builds its birth certificates on. Retain setpoints, modes, and status; do not retain high-rate streams or event logs (a new subscriber would get one stale event presented as current state). A retained message with an empty payload and the retain flag clears the stored value.

Sessions: surviving disconnects

With a persistent session (clean-start flag off, MQTT v5), the broker keeps a client's subscriptions and queues QoS 1/2 messages while it is offline, up to configured limits. This is store-and-forward for subscribers: a historian that reboots overnight can catch up on missed alarms. But queues are bounded — size them, monitor them, and set message expiry so a week-long outage does not replay ancient commands. For publishers, Sparkplug's birth/death flow on top of sessions is what turns reconnection into a well-defined state resync instead of a silent gap.

Defaults that work

Telemetry: QoS 0, no retain, persistent sessions on critical subscribers. State and setpoints: QoS 1, retained. Alarms: QoS 1, no retain, persistent subscriber sessions with expiry. Commands: QoS 1 with command-echo verification (or QoS 2 where duplication is dangerous). Document the policy per topic family — the next integrator will thank you.

References

Cite this page: MQTT QoS, retained messages, and sessions, explained, Shopfloor, 2026-09-21. https://shopfloorspace.yunusemrevurgun.com/articles/mqtt-qos-retained-sessions-explained/

Related