MQTT Fundamentals

MQTT Last Will and Testament (LWT): Detecting Offline Devices

Last Will and Testament lets the broker announce that a client vanished without saying goodbye. Learn the will fields, the exact trigger rules and how to test LWT by killing a client on a live broker.

Broker publishing an offline notice after a sensor disconnects, illustrating MQTT Last Will and Testament
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

MQTT Last Will and Testament (LWT) is the feature that lets a broker speak for a client that can no longer speak for itself. A device registers a "will" message when it connects, and the broker publishes it if that device disappears without a clean disconnect. By the end of this article you will know every will field, the precise conditions that trigger it, and how to test it yourself by killing a client connected to a live broker.

Why MQTT Needs a Last Will

MQTT is designed for unreliable networks. Devices lose power, firmware hangs, cellular links drop for minutes. In a pure publish/subscribe system, the publisher and subscriber never talk to each other directly, so nobody would notice that a sensor went silent until a human looked at a stale dashboard.

The MQTT broker is the only party that sees every connection. LWT turns that position into a feature: the client tells the broker in advance "if I vanish, publish this for me". Subscribers then learn about the failure through the same topics they already watch.

The Fields of MQTT Last Will and Testament

The will is set inside the CONNECT packet, so it must be configured before the client connects. It cannot be changed during a session; to change it, reconnect.

Field Purpose Typical value
Will topic Where the broker publishes the will site/line1/pump-07/status
Will payload Message body offline or {"state":"offline"}
Will QoS Delivery guarantee for the will 1
Will retain Whether the will becomes the retained value true
Will delay interval (MQTT 5) Seconds to wait before publishing 0 to a few seconds
Will properties (MQTT 5) Message expiry, content type, user properties Optional

Most production setups use QoS 1 and retain true. Retain is what makes the status useful to clients that connect later; without it, a dashboard that opens after the failure never learns the device is down. Retained behaviour is explained in detail in MQTT retained messages.

When the Broker Publishes the Will

The broker publishes the will when the network connection closes without a DISCONNECT packet. In practice that covers:

  1. The TCP connection is closed or reset by the client OS, for example a killed process.
  2. The keepalive timer expires. The broker waits roughly 1.5 times the keepalive interval with no packets before declaring the client dead.
  3. The client violates the protocol and the broker closes the connection.
  4. A network failure the broker detects through an I/O error.

It does not publish the will when:

  • The client sends a normal DISCONNECT. The will is discarded.
  • In MQTT 5, the client reconnects before the will delay interval expires, resuming its session.

That second rule is important: a clean shutdown produces no will. If you want "offline" on graceful shutdown too, publish it yourself before disconnecting. MQTT 5 also lets a client send DISCONNECT with reason code 0x04 (disconnect with will message) to ask the broker to publish the will anyway.

Testing LWT by Killing a Client

The fastest way to build intuition is to watch a will fire. We use the public MQTT test broker at broker.connectmq.com with a unique topic prefix.

Terminal 1, the watcher:

mosquitto_sub -h broker.connectmq.com -p 1883 -i lwt-watch-q81m \
  -t 'connectmq/demo/q81m/#' -v

Terminal 2, the "device". It registers a retained will, uses a 10-second keepalive, and stays subscribed so the process keeps running:

mosquitto_sub -h broker.connectmq.com -p 1883 -i lwt-device-q81m -k 10 \
  --will-topic connectmq/demo/q81m/device1/status \
  --will-payload offline --will-qos 1 --will-retain \
  -t connectmq/demo/q81m/device1/cmd

Terminal 3, announce the device as online with a retained birth message:

mosquitto_pub -h broker.connectmq.com -p 1883 -i lwt-birth-q81m \
  -t connectmq/demo/q81m/device1/status -m online -q 1 -r

Now kill the device abruptly. On Linux or macOS:

pkill -9 -f lwt-device-q81m

Terminal 1 prints connectmq/demo/q81m/device1/status offline almost immediately, because the operating system closed the socket and the broker saw it drop without DISCONNECT. If you instead pull the network cable or suspend a laptop, the will arrives only after the keepalive window passes, about 15 seconds with -k 10.

Try one more experiment: restart the device process and stop it with Ctrl+C. The Mosquitto tools send a proper DISCONNECT on Ctrl+C, so no will is published and the retained status stays whatever it was. That is the gap you close with an explicit offline publish on shutdown.

LWT in Python with paho-mqtt

Here is a complete device skeleton using paho-mqtt 2.x. It sets the will before connecting, publishes a retained birth message in on_connect (so it is repeated after every reconnect), and publishes "offline" on graceful exit:

import signal
import sys
import time
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
CLIENT_ID = "lwt-py-device-q81m"
STATUS = "connectmq/demo/q81m/device2/status"

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.will_set(STATUS, payload="offline", qos=1, retain=True)

def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print("connect failed:", reason_code)
        return
    client.publish(STATUS, "online", qos=1, retain=True)
    print("online")

def shutdown(signum, frame):
    client.publish(STATUS, "offline", qos=1, retain=True).wait_for_publish(timeout=5)
    client.disconnect()
    client.loop_stop()
    sys.exit(0)

client.on_connect = on_connect
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)

client.connect(BROKER, 1883, keepalive=15)
client.loop_start()
while True:
    time.sleep(1)

Run it, watch "online" appear in the watcher terminal, then kill it with kill -9 to see the broker-published will, or press Ctrl+C to see the script's own offline message.

Design Tips for Reliable Offline Detection

Pick a sensible keepalive. The keepalive sets the worst-case detection time for silent failures. 15 to 60 seconds is common for mains-powered devices. Very short values cost battery and bandwidth; very long ones delay alerts. Our guide to the MQTT keep alive interval covers the trade-offs.

Always pair LWT with a birth message. The will only says "offline". Something has to say "online" again after reconnecting, and it must be retained so it overwrites the retained will.

Use the same topic and retain flag for both. If the will is retained but the birth is not, new subscribers see "offline" forever.

Watch out for duplicate client IDs. If two devices share a client ID, the broker disconnects one when the other connects, and they kick each other off in a loop. Status flaps between online and offline. Make every client ID unique.

Consider a will delay in MQTT 5. A short delay prevents an "offline" flash when a device reconnects quickly after a network blip. See the MQTT will delay interval for details.

Include context in JSON payloads. A payload such as {"state":"offline","reason":"lwt"} lets consumers tell a crash from a planned shutdown.

Last Will and Testament on ConnectMQ

ConnectMQ supports LWT on both MQTT 3.1.1 and 5.0 connections, including retained wills. On a production broker you connect with the credentials from the portal (YOUR_USERNAME, YOUR_PASSWORD, YOUR_CLIENT_ID) over TLS on port 8883, and the will works exactly as in the examples above. Because client IDs on ConnectMQ are bound to issued credentials, the duplicate-ID flapping problem is easier to avoid.

For broker-side visibility in addition to LWT, ConnectMQ also exposes connection state on $SYS/broker/connection/{clientId}/state, which is handy for monitoring tools that should not depend on each device configuring its will correctly. If you are deciding where to host this, compare options in our hosted MQTT broker overview, and for the protocol fundamentals see the full MQTT tutorial.

Get Started with ConnectMQ

Sign up at app.connectmq.com and create a broker on the free Serverless plan, no credit card required. Point your devices at it with a retained Last Will and a birth message, and you have reliable online/offline status from day one.

Frequently Asked Questions

Is the Last Will published when a client disconnects normally?

No. A normal DISCONNECT tells the broker to discard the will. Publish your own offline message before disconnecting if you need one for planned shutdowns.

How long does it take for the broker to publish the will?

If the socket closes, it is almost immediate. If the device silently disappears, the broker waits about 1.5 times the keepalive interval, plus any MQTT 5 will delay interval.

Should the will message be retained?

Usually yes. A retained will ensures that clients connecting after the failure still see the device as offline.

Can I change the will after connecting?

No. The will is part of the CONNECT packet. To change it, disconnect and connect again with new will settings.

Related articles

Why Your MQTT Client Keeps Disconnecting (and How to Fix It)

Reconnect loops are one of the most common MQTT problems. Learn the five usual causes, from duplicate client IDs to keep alive timeouts and oversized packets, and follow a diagnosis flow that pinpoints yours.

8 min read

Who Invented MQTT? The History from Oil Pipelines to IoT

MQTT was invented in 1999 by Andy Stanford-Clark of IBM and Arlen Nipper of Arcom to monitor oil pipelines over satellite. Follow its path to open source, OASIS, ISO and today's managed cloud brokers.

7 min read

MQTT Maximum Message Size: Limits and Large Payload Strategies

MQTT can technically carry a 256 MB packet, but brokers, client libraries and devices impose far lower limits. Learn where the real limits are, what happens when you exceed them, and how to send large payloads.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.