Use MQTT as the device transport
Device state and commands move over a broker rather than over HTTP request/response between the platform and each device.
- Transport
- Devices
- MQTT
3 min read · 590 words
The forces at the time
What was chosen
nexus/<domain>/<zone>/set # command, QoS 1, not retained
nexus/<domain>/<zone>/state # reported, QoS 1, retained
nexus/<domain>/<zone>/available # LWT, QoS 1, retainedWhat else was considered
- HTTP endpoint per device
- Rejected. Requires stable addressing, a device inventory in the platform, and per-device retry logic; produces a visible stagger on group changes; gives devices no way to report state unprompted.
- Devices poll the platform
- Rejected. Removes the addressing problem but trades it for latency proportional to the poll interval, and constant traffic from every device whether or not anything has changed.
- WebSocket connection per device
- Rejected. Solves bidirectionality and gives push, but the platform is then responsible for connection state, fan-out, and reconnection for every device — which is a broker, written by hand and less well tested.
- MQTT with QoS 2 throughout
- Rejected. A four-step handshake and per-message broker state to achieve exactly-once, when the commands in question are naturally idempotent and QoS 1 is sufficient.
What follows
Gained
- Adding a device requires no change on the publishing side.
- A group change is one publish, so devices act simultaneously.
- Devices report state and availability without being polled.
- No inbound addressing or port forwarding to any device.
- Device failure is an explicit retained event rather than an inference from silence.
Paid for
- The broker is a platform service to run, secure, and keep alive, and a single point of failure for all device traffic.
- Debugging is harder: a message delivered to nobody is indistinguishable from one delivered to everybody without a subscriber tool in hand.
- Request/response interactions need a correlation pattern built on top, or a separate HTTP path.
- Topic names are unvalidated. A typo creates a live topic that silently receives messages nothing reads.
Records are immutable once accepted. A change supersedes this one rather than editing it.