Auf dieser Seite
Yes. Most IoT devices only need to talk to each other, and that does not require a route to the public internet. What you need is a broker or gateway on your own network, a clear idea of what must survive a dropped link, and the right MQTT settings to make it survive. This post covers those pieces, and what you give up.
What an IoT system needs to run
An IoT system has devices (sensors and actuators), gateways, a network and, usually, some cloud infrastructure. The cloud is the optional part. A thermostat that talks to a controller in the same house keeps working if the router goes down.
Offline systems replace the internet with something local. For MQTT that means a broker on your own network, a local place to make decisions, and a way for devices to reach both.
Four patterns for running offline
1. A local broker
The simplest option is a self-hosted MQTT broker on your own network, with devices connecting over Ethernet or Wi-Fi. Mosquitto is the usual starting point.
One thing catches people out when they set it up. Since Mosquitto 2.0, a broker started without any listener configured binds only to the loopback interface, and once you do configure a listener, anonymous connections are refused unless you allow them. So a fresh install will accept a test from the same machine and reject your sensors. A minimal config that opens the LAN with a password file and persistence looks like this:
listener 1883
password_file /etc/mosquitto/passwd
allow_anonymous false
persistence true
persistence_location /var/lib/mosquitto/
Give the broker a fixed address or a local DNS name so devices do not need to be reconfigured when the network changes. If you want to check the setup from a phone on the same Wi-Fi, a mobile MQTT client such as Mqtizer works for that.
2. Broker bridging
A bridge connects a local broker to another one, for example a site broker to a central broker. The local broker is the system of record for the site, and the bridge forwards the topics you choose when the link is up. In Mosquitto, each topic line sets a pattern, a direction and a QoS:
connection site-to-central
address central.example.com:1883
topic sensors/# out 1
cleansession false
With cleansession false, which is the default for bridges, the remote subscriptions persist if the connection drops. Messages that match can then queue for the bridge, up to the broker's max_queued_messages limit (1000 by default in Mosquitto, for QoS 1 and 2). Bridging QoS 0 gives you no queue, so choose the QoS on the bridge line deliberately.
3. Mesh and short-range radios
Some devices never speak IP over Wi-Fi or Ethernet at all. A few statements the vendors' own documentation supports:
- Thread is an IPv6-based protocol for low-power devices over an IEEE 802.15.4 wireless mesh, and its documentation lists self-healing mesh networking with no single point of failure as a core feature.
- Bluetooth LE supports point-to-point, broadcast and mesh topologies.
- LoRaWAN gateways convert radio packets to IP packets and relay them to a network server. Private networks are supported, and ChirpStack is an open-source network server for private or public LoRaWAN networks. Going offline therefore means running that server on your own network, because the gateway still needs an IP path to it.
Each of these ends at a gateway that translates to MQTT, so the local broker stays the meeting point. I have left out range figures on purpose. They depend on the hardware, antennas and building, so check the datasheet for the parts you plan to buy.
4. Edge processing
If the decision can be made on the device or on a nearby machine, it does not need a cloud round trip. A rule such as "turn the pump off above this pressure" belongs next to the pump. Cloud analytics can still consume the data later. This is a design choice more than a protocol feature, and it is the main reason an offline site can keep running safely.
Which MQTT features do the work
The offline behavior comes from a handful of protocol features. The MQTT specifications define all of them.
| Need | Feature | Notes |
|---|---|---|
| Do not lose messages for a client that drops off | Persistent session plus QoS 1 or 2 | The server stores subscriptions and QoS 1 and 2 messages for the client |
| New subscriber needs the latest value immediately | Retained message | Stored per topic. A zero-length retained publish deletes it |
| Know a device vanished | Last Will message | Published by the server after an unclean disconnect |
| Pick delivery guarantees | QoS 0, 1, 2 | At most once, at least once, exactly once |
Persistent sessions in 3.1.1 and 5
In MQTT 3.1.1 you set CleanSession to 0 and the server resumes the session for that client ID. The specification has no expiry mechanism, so how long the server keeps the session is up to the broker. In Mosquitto that is persistent_client_expiration, which never expires clients by default.
MQTT 5 replaces CleanSession with Clean Start and adds a Session Expiry Interval. If the interval is absent it is 0, so the session ends when the connection closes. The value 0xFFFFFFFF means the session never expires. Clean Start set to 1 with an interval of 0 is equivalent to CleanSession 1 in 3.1.1.
The practical rule is the same in both versions. A persistent session needs a stable client ID, and only QoS 1 and 2 messages are queued for the offline client. Mosquitto has an opt-in queue_qos0_messages setting, but the documentation calls that non-standard.
Try it with the Mosquitto tools
This sequence shows both a persistent session and a retained message. It assumes a broker at broker.local.
- In one terminal, subscribe with a fixed client ID and a persistent session, then stop it with Ctrl+C.
- In a second terminal, publish while the subscriber is offline.
- Run the subscribe command again with the same ID and the queued message arrives.
- Publish with
-rto keep the last known state on the broker for future subscribers.
mosquitto_sub -h broker.local -i dashboard-1 -c -q 1 -t 'site/+/temperature'
mosquitto_pub -h broker.local -q 1 -t site/boiler/temperature -m 71.5
mosquitto_pub -h broker.local -r -q 1 -t site/boiler/status -m online
The -c flag disables clean session and the Mosquitto documentation says -i must be set when you use it. Use QoS 1 on both the publish and the subscription, since QoS 0 messages are not queued.
Client libraries differ on buffering
Persistent sessions cover messages the broker is holding. Messages your device tries to publish while its own link is down are a client-side matter, and defaults differ. The Eclipse Paho Java client has its disconnected buffer disabled by default, and when you enable it the default capacity is 5000 messages. MQTT.js queues outgoing QoS 0 messages while disconnected by default. Read your library's documentation and test an unplugged cable before you trust it.
What you give up offline
Offline works, but it has costs.
- Remote access. You cannot monitor or fix a disconnected device from your desk. Someone has to be on site, and an offline alarm cannot send you a notification.
- Cloud services. Voice assistants, cloud dashboards and remote analytics stop until the link returns. Local processing can cover part of the gap.
- Cross-site coordination. Anything that needs data from another site waits. A bridge with a queue narrows the delay but does not remove it.
- Updates. Firmware and software updates need a path you control, such as a local file server or a technician with a laptop.
Practical tips for offline designs
- Decide what gets sent first when the link returns. Critical readings should go ahead of bulk logs, and separate topics make that easy to enforce.
- Design for both modes. A device that publishes to a local broker and lets a bridge handle the cloud works the same online and offline.
- Put safety logic at the edge, not in the cloud.
- Cap your queues. A broker queue or a client buffer that fills up drops messages, so choose limits that match how long an outage can last.
- Encrypt stored data and use real credentials on the local broker. A private network is not a trusted one.
Choosing your setup
Start with the failure you need to survive. If devices only need to talk to each other, a local broker with persistent sessions and a sensible QoS is enough. Add a bridge when a central site needs the data, and edge logic when decisions cannot wait. Connect to the internet when you have a reason to, not by default.
References
- MQTT Version 5.0 specification (OASIS)
- MQTT Version 3.1.1 specification (OASIS)
- mosquitto.conf manual page
- Migrating from Mosquitto 1.x to 2.0
- mosquitto_sub manual page
- mosquitto_pub manual page
- MQTT Essentials part 7: persistent session and message queuing (HiveMQ)
- Eclipse Paho Java DisconnectedBufferOptions
- MQTT.js README and client options
- Thread primer (OpenThread)
- Bluetooth technology overview (Bluetooth SIG)
- About LoRaWAN (LoRa Alliance)
- ChirpStack documentation
