MQTT Retained Messages and Last Will: Explained with Examples
MQTT provides two mechanisms for handling message persistence and client availability: retained messages and Last Will Testament. Retained messages ensure that new subscribers receive immediate state. Last Will ensures that monitoring systems detect when devices go offline. Both are critical for building reliable IIoT systems, but they serve different purposes and are often misunderstood.
This guide explains what retained messages and Last Will actually do, when to use each, and how they compare to the more sophisticated Sparkplug B birth/death certificates. It includes concrete topic/payload examples you can apply directly to your MQTT implementation.
Retained Messages: State for New Subscribers
When a client publishes a message with the retain flag set to true, the MQTT broker stores that message on the topic. When a new client subscribes to that topic, the broker immediately sends the retained message. The subscriber receives the last known value without waiting for the publisher to send an update.
How Retained Messages Work
The retained message lifecycle:
- Client A publishes to
sensor/temperaturewith payload72.5and retain=true. - The broker stores this message for topic
sensor/temperature. - Client A disconnects. The broker keeps the stored message.
- Client B subscribes to
sensor/temperature. - The broker immediately sends Client B the retained message (72.5).
- Client B receives the current temperature without waiting for Client A to publish again.
The broker only stores one retained message per topic. When a new message with retain=true is published, it replaces the previous retained message. When a message with retain=false is published, it clears the retained flag for that topic (the broker stops storing a retained message for that topic).
When to Use Retained Messages
Use retained messages for state data — information that represents "what is true right now" rather than "what just happened."
Good Use Cases:
- Device Configuration: Publish configuration on boot with retain=true. When monitoring systems connect, they immediately receive the device's current configuration without waiting for the device to publish it again.
- Current Setpoint: If a device has a configurable setpoint, publish the setpoint with retain=true whenever it changes. New subscribers immediately receive the current setpoint.
- Device Status: Publish device status (online/offline/maintenance) with retain=true. Status is state, not an event.
- Capabilities and Limits: Publish device capabilities (max temperature, supported modes) with retain=true. These are static properties that new subscribers need.
Bad Use Cases:
- Events: An alarm like "High Temperature Detected" is an event, not state. It should not be retained.
- Time-Series Data: Temperature readings every second are time-series data, not state. They should not be retained (the broker would be overwhelmed).
- Commands: A command like "Start Motor" is an action, not state. Retaining commands causes confusion — new subscribers should not receive old commands.
Concrete Example: Device Configuration
Topic: device/sensor-001/config
Payload: {"interval": 5, "unit": "F", "enabled": true}
Retain: true
Topic: device/sensor-001/interval
Payload: 5
Retain: true
When the device boots, it publishes its configuration with retain=true. When an HMI or monitoring system subscribes to device/sensor-001/config, it immediately receives the current configuration. If the device reboots and changes its configuration, it publishes the new configuration with retain=true, replacing the old retained message.
sensor/temperature with retain=true, then publish to the same topic with retain=false, the broker clears the retained flag. If you want to clear a retained message, publish a zero-length payload with retain=true (this explicitly stores an empty message) or publish with retain=false (this clears the retain flag).
Last Will Testament: Detecting Device Failures
Last Will Testament (LWT) is a message that the client specifies when it connects to the broker. If the client disconnects ungracefully (crashes, loses network connection, power failure), the broker publishes the Last Will message on the client's behalf. If the client disconnects gracefully (sends DISCONNECT packet), the broker does not publish the Last Will.
How Last Will Works
The Last Will lifecycle:
- Client connects to the broker with LWT topic
device/sensor-001/statusand payloadoffline. - Client operates normally, publishing and subscribing.
- Client crashes or loses network connection without sending DISCONNECT.
- Broker detects the abnormal disconnection (typically via keepalive timeout).
- Broker publishes the LWT message to
device/sensor-001/statuswith payloadoffline. - Monitoring systems subscribed to
device/sensor-001/statusreceive the offline notification immediately.
The Last Will is specified per connection, not per client application. If the client application creates multiple connections, each connection can have its own Last Will.
When to Use Last Will
Use Last Will for detecting device failures, network issues, and abnormal disconnections. It is the primary mechanism for device online/offline status in MQTT.
Common Use Cases:
- Device Online/Offline Status: Publish LWT to
device/{id}/statuswith payloadoffline. When the device connects, it publishesonlineto the same topic (optionally retained). When it disconnects abnormally, the broker publishesoffline. - Failure Detection: Monitoring systems subscribe to device status topics. When they receive
offline, they trigger alerts, notify operators, or initiate failover procedures. - Network Health Monitoring: If many devices in the same subnet go offline simultaneously, the LWT messages indicate a network switch or router failure, not individual device failures.
- Graceful vs Abrupt Shutdown: If a device publishes
shutting_downbefore disconnecting gracefully, and the LWT isoffline, monitoring systems can distinguish planned maintenance from failures.
Concrete Example: Device Status Pattern
Connection LWT:
Topic: device/sensor-001/status
Payload: offline
QoS: 1
Retain: true (optional - see below)
On Connect:
Topic: device/sensor-001/status
Payload: online
Retain: true (if you want new subscribers to see current status)
On Graceful Shutdown:
Topic: device/sensor-001/status
Payload: offline
Retain: true
Then: Send DISCONNECT packet (LWT is not published)
In this pattern, the device publishes online when it connects and offline when it shuts down gracefully. If it crashes or loses network, the broker publishes the LWT offline. Monitoring systems subscribe to device/sensor-001/status and immediately detect the device state.
Should LWT Be Retained?
There are two schools of thought:
Retained LWT: Set retain=true on the Last Will topic. When a device goes offline, the offline message is retained. New subscribers immediately see that the device is offline. This provides accurate state but can cause confusion — if a device reconnects and publishes online with retain=true, the retained message becomes online. If it then disconnects again, the broker publishes LWT offline which is retained. This works, but it requires careful coordination.
Non-Retained LWT: Set retain=false on the Last Will topic. The offline message is not retained. New subscribers do not immediately see the offline status; they must wait for the next status update. This avoids confusion but means new subscribers have incomplete information.
online and offline) so new subscribers get current state. But be aware that the retained message will change as devices connect and disconnect. If you need a persistent "device is offline" indicator, use a separate topic or database.
Retained Messages vs Last Will: Direct Comparison
These mechanisms solve different problems but are often confused because both involve messages that persist beyond disconnections.
The key distinction: retained messages are about state. Last Will is about events. Retained messages ensure that new subscribers get the current state. Last Will ensures that monitoring systems detect when something goes wrong.
Sparkplug B: Birth and Death Certificates
Sparkplug B is an MQTT payload specification that formalizes and extends retained messages and Last Will. It includes both concepts in a standardized format.
Sparkplug Birth Certificate
When a Sparkplug device connects, it publishes a birth message. This message includes:
- Device metrics (all data points the device publishes)
- Metric definitions (names, types, units)
- Initial values for all metrics
- Quality indicators
The birth message is published with retain=true. New subscribers receive the complete device state and data model immediately. This is a superset of retained messages — not just the current value, but the entire structure of what the device publishes.
Sparkplug Death Certificate
The Sparkplug death certificate is essentially a Last Will. When a Sparkplug device connects, it specifies a Last Will topic and payload. If the device disconnects abnormally, the broker publishes the death message.
The death message includes:
- Device identifier
- Death timestamp
- Optionally, the sequence number of the last valid message
Subscribers receive the death message and know that the device is offline. More importantly, Sparkplug defines a birth sequence number. When the device reconnects and publishes a new birth message, subscribers can detect if any messages were lost during the outage.
Why Sparkplug B Matters
Without Sparkplug B, you must define your own conventions for retained messages and Last Will. Every device vendor might use different topic naming, different payload formats, and different status values. Sparkplug B standardizes this:
- Standardized Topics:
spBv1.0/<group>/<message type>/<edge node> - Standardized Payloads: Binary encoding with defined structure for metrics, quality, and metadata
- Birth/Death Semantics: Well-defined birth and death certificates with sequence numbers
- Alias Compression: After birth, subsequent messages use numeric aliases instead of repeating metric names
Common Anti-Patterns
Retaining Time-Series Data
Do not retain time-series data like temperature readings every second. The broker will store a new retained message for each reading, overwhelming broker storage and confusing new subscribers (they receive only the latest reading, not history). Time-series data belongs in a time-series database, not in retained messages.
Retaining Commands
Do not retain command messages. If a command like START_MOTOR is retained, new subscribers will receive an old command that may no longer be relevant. Commands are events, not state. Publish commands without the retain flag.
Last Will Without Online Status
If you use Last Will to publish offline, also publish online when the device connects. Otherwise, monitoring systems know when devices go offline but do not know when they come back online. The status topic should reflect both states.
Confusing Retained Messages with Persistence
Retained messages are not a persistence mechanism. They store only one message per topic, and only for topics that have active retained messages. They are not a database. If you need persistent storage for historical data, use a database or time-series store, not retained messages.
Last Will with retain=true on Every Topic
Do not set retain=true on every Last Will topic. If you have 1000 devices and each has an LWT with retain=true, the broker stores 1000 retained messages for status topics. This is fine. But if every data topic also has retain=true "just in case," the broker will be overwhelmed. Use retain=true selectively for state topics only.
How Voltrus MQTT Explorer Works with Retained Messages and Last Will
Voltrus MQTT Explorer is a native macOS application for debugging and monitoring MQTT brokers. It provides tools for working with retained messages and Last Will.
Retained Message Inspection
MQTT Explorer can query the broker for retained messages. It shows all topics that have retained messages and displays the retained payload. This is useful for debugging — you can verify that a device is publishing its configuration with retain=true, and you can see exactly what the retained message contains.
Clearing Retained Messages
MQTT Explorer allows you to clear retained messages. Publish a zero-length message with retain=true, or publish with retain=false, to clear the retained flag for a topic. This is useful when you are testing and want to reset the broker's retained message state.
Last Will Configuration
When you connect to a broker with MQTT Explorer, you can configure the Last Will. Specify the LWT topic, payload, QoS, and retain flag. This allows you to test LWT behavior — connect with an LWT, then kill the network connection, and observe whether the broker publishes the LWT.
Monitoring Device Status
MQTT Explorer can subscribe to device status topics and display online/offline transitions. If you are debugging a device that uses LWT for status, subscribe to device/{id}/status and watch the messages flow. When the device goes offline, you immediately see the LWT offline message.
Sparkplug B Support
MQTT Explorer includes Sparkplug B payload decoding. When you subscribe to Sparkplug topics, the app decodes the binary payload and displays the metrics in a human-readable format. You can see birth certificates, death certificates, and data messages with proper metric names, types, and values.
Frequently Asked Questions
What is the difference between MQTT retained messages and Last Will?
Retained messages store the last published message on a topic so new subscribers receive it immediately upon subscription — useful for state data like device configuration. Last Will is a message that the broker publishes on the client's behalf if the client disconnects ungracefully — useful for device online/offline status and failure detection. Retained messages are about preserving state; Last Will is about detecting absence.
When should I use MQTT retained messages?
Use retained messages for state data that new subscribers need immediately, without waiting for the next update. Examples: device configuration (publish on boot and retain), current setpoint (subscribers need the current value immediately), device capabilities and limits. Do not use retained messages for events or time-series data — only for relatively stable state that represents 'what is true right now'.
When should I use MQTT Last Will?
Use Last Will for detecting device failures and network issues. When a client connects, it specifies a Last Will topic and message. If the client disconnects ungracefully (crashes, network drops, power loss), the broker publishes the Last Will message. This allows monitoring systems to immediately detect that a device has gone offline. Common pattern: publish LWT to 'device/{id}/status' with payload 'offline' on disconnect.
How do MQTT retained messages and Last Will compare to Sparkplug B?
Sparkplug B includes both concepts: the birth message is retained (declares the device's data model and initial state), and the death message is essentially a Last Will (published when the device disconnects). Sparkplug B formalizes and extends these concepts with structured payloads, alias compression, and birth/death certificates that include device metrics and quality indicators. Sparkplug B is essentially a standardized implementation of retained messages and Last Will with industrial data modeling.
Can an MQTT message be both retained and have a Last Will?
Yes, these are independent features. Retained is a flag on a published message. Last Will is configured per client connection. A client can publish retained messages and also have a Last Will configured. For example, a device might publish its current state with retain=true on topic 'device/{id}/state', and also configure Last Will on topic 'device/{id}/status' with payload 'offline'. These serve different purposes — retained state vs failure detection.
Debug MQTT on macOS
Voltrus MQTT Explorer connects to any broker, supports SSL/TLS and WebSockets, inspects retained messages, configures Last Will, and decodes Sparkplug B payloads. Native macOS app, no Java required. $49 lifetime.
Explore MQTT Explorer