· Eduardo Vieira · Industrial Protocols · 5 min read
MQTT QoS, Retained Messages, and Persistent Sessions
Choose MQTT delivery semantics by message purpose without mistaking broker acknowledgement for physical effect.

MQTT QoS, retained messages, and persistent sessions
MQTT delivery options are useful only when they match the meaning of a message. QoS, retained state, sessions, and wills control protocol behavior between clients and broker. They do not make a value fresh, confirm a physical effect, or replace local interlocks and safety ownership.
Read the QoS table literally
| QoS | MQTT delivery intent | Application consequence |
|---|---|---|
| 0 | At most once | Loss is possible; no retransmission handshake |
| 1 | At least once | A receiver can see duplicates |
| 2 | Exactly once in the MQTT protocol flow | Extra handshake and state; not exactly once in a process |
QoS 0 fits high-rate, noncritical telemetry when a newer sample soon replaces an older one. QoS 1 fits events or alarms when the application can tolerate duplicate delivery. QoS 2 adds protocol exchanges and state, so use it only after showing that its cost and failure modes are justified. Broker acknowledgement at any QoS says the broker handled the protocol operation; it does not confirm a historian write, actuator movement, operator action, or safe machine state.
Treat DUP as transport information
The DUP flag indicates retransmission semantics. It does not identify one business event and cannot decide whether a consumer has already applied an operation. Put a stable event_id in event messages and make the consumer idempotent: storing the same alarm transition twice must not create two work orders, and a repeated state message must not trigger a second action.
A sequence can help within one source epoch, but reconnect and reset rules must be explicit. Do not use broker arrival order as a universal order across publishers. Application identity, ordering, and compensation remain application responsibilities even when QoS 2 is selected.
Understand retained state
A retained publish stores one last message for a topic and delivers it to later matching subscribers. It is a convenient last-known state, not a history stream. Publish an empty retained payload to delete the retained message. Retained state exists outside a particular subscriber session, so a client with a new or clean session can still receive it.
Every retained contract needs source time and freshness handling. A retained value can be hours old after a device failure or network partition. Consumers must check measured time, quality, and expiry before treating it as usable. Never use retained state alone as proof that an actuator is off, a guard is closed, or a process is safe.
Separate Clean Start and Session Expiry
Clean Start tells the broker whether to discard existing session state when the client connects. Session Expiry tells it how long state may survive after disconnect. Depending on the negotiated session, that state can include subscriptions, queued QoS messages, and incomplete QoS flows. It does not preserve arbitrary application memory or make a disconnected client healthy.
Choose session persistence by client role. A disposable dashboard can use Clean Start and subscribe again. A collector that needs bounded offline QoS 1 delivery can request a short, intentional Session Expiry and monitor queue limits. Long persistence without quotas merely moves an outage into broker storage pressure.
Expire messages before queues expire
Message Expiry Interval limits how long a publication remains useful. It is distinct from Session Expiry and from retained-state deletion. Broker and client offline queues are finite, so establish byte and count limits, expiry behavior, and a health alarm before a backlog becomes an availability issue.
Expired telemetry should not be replayed as if it were current. For events, decide whether late delivery remains useful, needs a late-data path, or should be dropped with an explicit gap. Size store-and-forward buffers separately from broker queues and document which layer owns each retention decision.
Use Last Will within its boundary
A Last Will can tell subscribers that a client connection ended unexpectedly. Will Delay can postpone its publication, Will Retain can retain the notice, and expiry can limit how long it remains visible. These controls help communicate connection state, not process state.
A will may be delayed by a transient network outage, suppressed by a clean disconnect, or delivered while the field device continues operating. Do not map it directly to safe/off, emergency stop, or permissive logic. Those functions need local signals, safety-rated design where required, and an approved timeout response.
Choose configurations by purpose
For high-rate noncritical telemetry, use QoS 0, no retained payload, and short Message Expiry if old data is useless. The pitfall is treating missing packets as an alarm without a separate freshness rule.
For alarms or discrete events, use QoS 1, event_id, idempotent consumers, a bounded Session Expiry for the collector if needed, and an explicit late-event policy. The pitfall is assuming QoS 1 removes duplicates.
For last-known configuration or connectivity status, use a retained message containing source time, quality, and a defined expiry. A short session policy may serve the publisher, but retention is independent. The pitfall is showing an old retained state as a live operational fact.
Secure the topic boundary
Use TLS where supported, topic ACLs that constrain publisher and subscriber identities, network zoning, and least privilege. A telemetry identity should not publish command topics, and a cloud subscriber should not obtain a route to PLC or fieldbus control. Rotate credentials through the approved process and keep secrets out of payloads, client logs, and examples.
NIST and CISA guidance place broker deployment inside an OT architecture. A convenient internet path is not a substitute for segmentation, reviewed remote access, and ownership of the exposed interface.
Run an operational checklist
Confirm QoS by message purpose; confirm event_id and duplicate behavior; confirm retained creation, replacement, and deletion; confirm Clean Start and Session Expiry; set Message Expiry and queue limits; test a delayed will; review ACLs and TLS; and record source-time freshness rules. Test broker restart, client reconnect, duplicate delivery, retained stale data, full offline queue, and expired message behavior.
Continue with MQTT payload design, Sparkplug lifecycle, resilient store-and-forward, and IIoT cloud services.
References
- OASIS, MQTT Version 5.0.
- OASIS OpenC2, MQTT transfer specification.
- Microsoft, Azure IoT Operations disk persistence.
- NIST, SP 800-82r3.
- CISA, ICS recommended practices.



