An industrial MQTT client reconnects after losing network access. Should it receive the latest equipment state, or every eligible message published while it was offline? Those are different requirements, and MQTT uses different mechanisms to address them.
A retained message helps a subscriber learn the last retained value on a topic when it subscribes. A persistent session helps an existing subscriber resume its subscriptions and receive eligible queued or unacknowledged messages after a disconnection. Neither is a substitute for an industrial historian.
Compare the two mechanisms
| Question | Retained message | Persistent session |
|---|---|---|
| What does it preserve? | The current retained message for a topic | Client session state, including subscriptions and eligible pending messages |
| Who is it associated with? | The topic on the broker | A client identifier and its session |
| When is it useful? | A new subscription needs an initial last-known state | A returning subscriber needs to continue after a disconnect |
| Does it preserve every published reading? | No; a later retained publication replaces the earlier retained message | Not automatically; only eligible queued or unacknowledged messages within limits |
| Does it create queryable history? | No | No |
The distinction is set out in the OASIS MQTT 5.0 specification. Retained messages are not part of a client’s Session State, and ending that session does not, by itself, delete the topic’s retained message.
Retained messages answer: What is the latest known state?
Consider a packaging line publishing plant/line2/packer/status. The application publishes RUNNING with the RETAIN flag set. Later, a new maintenance display subscribes to that topic. If the retained message remains available and the subscription’s retain-handling settings permit it, the broker delivers the retained RUNNING state without waiting for the next live publication.
When a new retained publication changes the state to STOPPED, it replaces the earlier retained state for that topic. The broker is not storing a sequence of RUNNING, FAULT, and STOPPED events as a historian would. A retained value can also become stale if the publisher disappears without updating the topic.
For operational use, include enough context to interpret the state, such as a source timestamp and device identity in the application payload. A retained RUNNING value without a freshness check must not be treated as proof that the machine is still running.
A retained message is delivered as part of subscription behavior, not simply because an existing session reconnects. MQTT 5.0 also provides Retain Handling options that can suppress or limit retained delivery when a subscription is created. Retained messages are not sent on creation of a shared subscription. Check the subscribing client’s behavior rather than assuming every reconnect replays a retained value.
Persistent sessions answer: What can this client resume?
Now consider a historian collector that subscribes to plant/line2/+/temperature. Its network connection fails for several minutes while the broker continues receiving data.
If the collector has an appropriate persistent session, the broker can retain that client’s subscriptions and eligible QoS 1 or QoS 2 messages while it is disconnected. When the client returns with the same client identifier and resumes the existing session, it can receive the queued work that remains available. QoS 0 offline queuing is optional under MQTT 5.0, so do not design recovery around it without verifying broker behavior.
This is useful, but it is conditional. The session may expire. Individual messages may expire. Broker queue limits, administrative actions, outages, and storage configuration can reduce or eliminate what survives. Also, if the source never delivered measurements to the broker, the subscriber’s persistent session cannot recover them.
The phrase persistent session means that MQTT session state can continue beyond one network connection. It does not promise durable disk storage through every broker restart or unlimited offline retention.
MQTT 5.0 Clean Start and Session Expiry are separate decisions
For MQTT 5.0, consider two settings together:
- Clean Start: When set to 1, the connection starts a new session and discards an existing session for that client identifier. When set to 0, the client asks to resume an existing session if one is available.
- Session Expiry Interval: Controls how long the session can remain after the network connection closes. The default is 0 when the property is absent, so the session ends at disconnect unless a nonzero interval applies.
For an offline-recovery use case, use a stable, unique client identifier, request a resumable session, and configure an appropriate nonzero Session Expiry Interval. After reconnecting, inspect the broker’s session-present indication to see whether the earlier session actually survived. Do not assume that setting Clean Start to 0 creates a long-lived session by itself.
MQTT 3.1.1 uses a Clean Session flag rather than the separate MQTT 5.0 controls. A guide written for one protocol version should not silently substitute its settings for the other.
MQTT 5.0 also supports Message Expiry Interval. A queued message whose allowed lifetime has elapsed can be removed before onward delivery, even when the client’s session still exists. Session lifetime and message lifetime solve different problems.
Which should an industrial system use?
Use retained messages for values a subscriber needs immediately after joining: the latest machine mode, a gateway configuration version, or another explicitly maintained current state. Make sure the payload includes a way to detect staleness.
Use persistent sessions when an existing collector or monitoring service needs continuity across a temporary disconnection. Confirm the broker’s queue policy and the subscription QoS, and test with the actual expected outage duration. A session is not an archive.
Some systems need both. A newly connected dashboard may require one retained operating state, while a historian collector may need eligible queued measurements after reconnect. But if every second of production history matters, those mechanisms alone leave important gaps in the design.
The larger requirement is to preserve, timestamp, validate, and query each measurement. That calls for application-level buffering where needed, controlled ingestion, and a historian or time-series database such as TDengine TSDB. A broker can support the transport path without taking over the historian’s job.
Test the exact behavior before relying on it
A short field test reveals more than a feature checkbox:
- Publish a retained equipment state, create a fresh non-shared subscription, and confirm what state arrives.
- For an MQTT 5.0 test, first establish a subscription with QoS 1 or 2, confirm the granted QoS, and use a stable client identifier with a nonzero Session Expiry Interval. Disconnect the subscriber, then publish several matching QoS 1 messages while it is offline.
- Reconnect the same client without clearing its prior session. Check whether the broker reports that the old session was present and which queued messages arrived.
- Repeat after session expiry, message expiry, and a broker restart configured according to your deployment’s persistence policy.
- Compare the received messages with actual historian rows, including timestamps, duplicates, and gaps.
For TDengine TSDB Enterprise deployments, the MQTT ingestion connector can subscribe to broker topics and map messages into historical tables. Its documentation lists MQTT protocol selection and a Clean Session setting. Verify the available session controls and actual recovery behavior for the deployed version and broker rather than assuming every MQTT 5.0 session option is exposed by the connector. Do not infer durable end-to-end history from the connector’s MQTT subscription alone.
The practical rule: retained messages help subscribers initialize their view of a topic; persistent sessions help eligible message delivery continue across connections. Historical completeness is a separate engineering requirement, and it needs its own verification.


