Configure LWT in every device's CONNECT packet: set willTopic to devices/<id>/status, willMessage to {"online":false}, willQoS to 1, and willRetain to true so new subscribers immediately see the last known status
On successful connection, immediately publish {"online":true} with retained=true to the same devices/<id>/status topic to overwrite the LWT from any previous session; this establishes a clear online indicator
Implement an application-level heartbeat: have each device publish a small message (e.g., {"ts":<epoch_ms>}) to devices/<id>/heartbeat on a fixed interval (e.g., every 60 seconds) independent of telemetry traffic
On the backend, maintain a last-seen timestamp per device updated on every heartbeat receipt; run a periodic job (e.g., every 30 seconds) that compares now() against last-seen and marks devices as offline if they have not been heard within 2-3 heartbeat intervals
Combine both signals: use LWT for fast detection of clean disconnects and the heartbeat timeout for detecting silent failures (device hangs, network black-hole) where TCP stays open but the device stops sending
Emit offline events to an alerting or logging system when a device transitions to offline; include the last-seen timestamp and the reason (LWT vs heartbeat timeout) to distinguish clean disconnects from crash or network failure scenarios
Known gotchas
LWT is only published on unclean disconnect; a device that calls MQTT DISCONNECT cleanly (e.g., a graceful shutdown) will not trigger LWT — the device must publish its own offline message before disconnecting in this case
The broker may not publish LWT immediately upon disconnect; some brokers apply a short delay or wait for the keepalive period to expire before confirming the client is gone — do not rely on LWT for sub-second offline detection
Heartbeat timeouts must account for expected periods of silence such as scheduled deep sleep on battery devices; use device-type-specific timeout thresholds rather than a single global value to avoid false offline alerts for low-power devices
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp