MQTT: A Protocol Designed for Disconnection
While the web asks and waits for an answer, the world of things has been talking a different way. An introduction to publish/subscribe, and to the design philosophy of a protocol that even prepares a last will.
The conversation we have grown used to on the web is request and response. The browser asks the server, “Give me this page,” and the server answers. Ask nothing, and nothing happens. This is perfectly natural when a person sits in front of a screen and wonders about something.
Step into the world of things, though, and the story changes. Say you have two hundred temperature sensors hanging from a warehouse ceiling. For a server to ask them “what’s the temperature?”, it has to ask two hundred times — and it has no idea when to ask. Ask every minute and you have bothered 199 sensors that had nothing new to say. Ask every ten minutes and a freezer can thaw in between without anyone knowing. On top of that, these sensors run on batteries, their signal is weak, and they drop off constantly.
MQTT was born in exactly that situation. In 1999, Andy Stanford-Clark of IBM and Arlen Nipper of Arcom built it to monitor oil pipelines across the desert over satellite links. Satellite is slow, expensive, and unreliable. So the protocol had to be light — and above all, it had to treat disconnection as normal. That origin explains nearly every design decision in MQTT.
Don’t ask. Announce.
MQTT’s first move is to stop asking. A sensor asks no one anything; it simply publishes what it knows. “warehouse/freezer-a/temperature is -18.2.” That statement goes to an intermediary called a broker. Anyone curious about that fact has already subscribed with the broker: “Tell me when warehouse/freezer-a/temperature changes.”
The sensor doesn’t know who is listening. The listeners don’t need to know which sensor spoke. The two are joined by nothing but a name — the topic. A database recording temperatures, an alerting service, an admin dashboard: if all three subscribe to the same topic, the sensor still publishes exactly once. Not a single line of the sensor’s code changes.
Topics form a hierarchy with slashes, and subscriptions can use wildcards.
warehouse/freezer-a/temperature ← just this one
warehouse/+/temperature ← every freezer's temperature (+ is one level)
warehouse/# ← everything under warehouse (# is the rest)
In code it comes to about this much. Once you know the broker’s address, the rest is two verbs.
import mqtt from 'mqtt';
const client = mqtt.connect('mqtt://broker.local');
// the listening side
client.subscribe('warehouse/+/temperature');
client.on('message', (topic, payload) => {
console.log(topic, String(payload)); // warehouse/freezer-a/temperature -18.2
});
// the speaking side
client.publish('warehouse/freezer-a/temperature', '-18.2');
Three devices for handling absence
So far this is not far from any other publish/subscribe system. What let MQTT survive in the world of things comes next.
First, QoS — the level of delivery guarantee. Level 0 just throws the message (no confirmation that it arrived). Level 1 resends until it arrives (so it may arrive more than once). Level 2 adds another round trip so it arrives exactly once (and is correspondingly slower). For a temperature that will be superseded by a fresh reading a second later, 0 is plenty; a command like “open the door” needs 1 or 2. Rather than handing you reliability for free, MQTT lets you pay for it per message.
Second, the retained message. The broker holds on to the last value for each topic. When you open the admin dashboard, there is no reason to stare at an empty screen for minutes until the next temperature report arrives. The moment you subscribe, the last known value lands. For any system that deals in state, this is a bigger convenience than it first appears.
Third — and this is the most characteristically MQTT of them all — the Last Will and Testament. When a device connects, it hands the broker its will in advance: “If I vanish without saying goodbye, announce ‘offline’ on this topic for me.” Later, when the device truly dies, loses power, or falls off the network, the broker notices the absence and publishes the will on its behalf.
mqtt.connect('mqtt://broker.local', {
will: { topic: 'warehouse/freezer-a/status', payload: 'offline', retain: true },
});
Designing absence into the system
The idea of a will is worth pausing on. Most protocols design what will be exchanged while the connection is alive. MQTT goes a step further and designs what will be said after the connection is gone. Disappearance is treated not as an exception to handle but as an ordinary event.
That is a lesson from the pipeline in the desert. Satellite links drop. That is not a bug to be fixed but a condition to be accepted. When you design on top of a condition instead of denying it, you tend to get a sturdier thing. That, I think, is why MQTT is still connecting factories, cars, and the light bulbs in our homes two decades on.
Much of what we build is like this too. Users close the app halfway through, the signal dies in the subway, a payment stalls without an answer. Do we call those moments exceptions and hurry to paper over them — or do we assume from the start that they will happen, and prepare in advance what should be said when they do? MQTT chose the latter, and I suspect that choice is less a technical decision than a stance.