← All Posts

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:

  1. Client A publishes to sensor/temperature with payload 72.5 and retain=true.
  2. The broker stores this message for topic sensor/temperature.
  3. Client A disconnects. The broker keeps the stored message.
  4. Client B subscribes to sensor/temperature.
  5. The broker immediately sends Client B the retained message (72.5).
  6. 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.

Only one retained message per topic. If you publish to 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:

  1. Client connects to the broker with LWT topic device/sensor-001/status and payload offline.
  2. Client operates normally, publishing and subscribing.
  3. Client crashes or loses network connection without sending DISCONNECT.
  4. Broker detects the abnormal disconnection (typically via keepalive timeout).
  5. Broker publishes the LWT message to device/sensor-001/status with payload offline.
  6. Monitoring systems subscribed to device/sensor-001/status receive 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}/status with payload offline. When the device connects, it publishes online to the same topic (optionally retained). When it disconnects abnormally, the broker publishes offline.
  • 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_down before disconnecting gracefully, and the LWT is offline, 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.

The best practice combines both approaches. Use retain=true for status messages (both 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.

Characteristic
Retained Messages
Last Will
Primary Use
Purpose
Preserve state for new subscribers
Detect abnormal disconnections
State / Failure
Trigger
Publish with retain=true
Abnormal disconnect
Client / Broker
Recipient
New subscribers only
All subscribers to LWT topic
Targeted / Broadcast
Persistence
Until replaced or cleared
One-time message
Long / Short
Scope
Per topic
Per connection
Topic / Client
Clearing
Publish with retain=false
Graceful disconnect
Explicit / Automatic
Typical QoS
0 or 1
1 (at least once)
Both valid

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
Sparkplug B is retained messages and Last Will, industrialized. It takes the concepts of state preservation and failure detection and adds data modeling, sequence numbers, and payload standardization. If you are building an industrial MQTT system, use Sparkplug B instead of ad-hoc retained messages and Last Will conventions.

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.

MQTT Explorer runs natively on macOS. No Java, no cross-platform limitations. Universal binary for Intel and Apple Silicon. $49 for a lifetime license. If you are debugging MQTT devices, testing retained messages and Last Will, or monitoring Sparkplug B traffic, this tool provides everything you need.

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

Further Reading