MQTT is a lightweight publish/subscribe messaging protocol that has become the default transport for sending field data from plant-floor devices up to dashboards, historians, and SCADA systems. Instead of every client polling every device, sensors and gateways publish readings to named topics on a central broker, and any number of consumers subscribe to the topics they care about. This decoupling, plus tunable delivery guarantees and a tiny wire footprint, is why MQTT 3.1.1 and MQTT 5.0 are now standard in industrial IoT (IIoT) architectures.
The broker and client model
MQTT has exactly two roles. The broker (Mosquitto, EMQX, HiveMQ, or a cloud service) is the central message router. Clients are everything else: a Modbus-to-MQTT gateway, a PLC with a native MQTT stack, a SCADA node, a historian, or a mobile dashboard. A client never talks directly to another client. It only opens a TCP connection to the broker, then publishes and subscribes. The broker matches each published message against the subscription filters of all connected clients and forwards copies accordingly.
This star topology is what makes MQTT scale. Adding a new dashboard does not require touching a single field device. The new client simply subscribes to the relevant topics, and the broker handles fan-out. In a typical SURIOTA deployment, an SRT-MGATE-1210 Modbus-to-MQTT gateway reads RS-485 registers from meters and sensors, then republishes each value as an MQTT message, turning legacy serial equipment into a publisher on the network.
Designing the topic hierarchy
Topics are UTF-8 strings split into levels by forward slashes, for example plant1/utilities/line3/meter07/power_kw. There is no central schema. The hierarchy is a convention you define, so getting it right early saves painful migrations later. A robust IIoT scheme moves from broad to specific: site / area / line / device / metric.
- site: the physical plant or location identifier (plant1, jakarta_dc).
- area: a process area or building zone (utilities, packaging, compressor_room).
- line: a production line or feeder (line3, feeder_a).
- device: the specific asset, ideally tied to a serial number or asset tag (meter07, pump_p101).
- metric: the individual measurement (power_kw, temp_c, status, vibration_mm_s).
Keep levels lowercase, avoid spaces, and never put a leading slash (an empty first level is legal but wasteful). Do not encode values that change (like a setpoint) into the topic name itself; topics identify what a message is, the payload carries the value. Many teams adopt the Sparkplug B specification, which standardises the topic namespace (group/edge_node/device) and payload encoding on top of MQTT for exactly this reason.
Wildcards for subscriptions
Publishers always use a fully specified topic. Subscribers may use two wildcard characters. The single-level wildcard + matches exactly one level: plant1/+/+/+/power_kw returns power from every device in the plant. The multi-level wildcard # matches everything below a point and must be the last character: plant1/utilities/# delivers every metric from the utilities area. A SCADA historian might subscribe to plant1/# to capture all data, while a single-screen dashboard subscribes only to the handful of topics it renders.
Quality of Service: QoS 0, 1, and 2
QoS sets the delivery guarantee for each published message and each subscription. It is chosen independently on the publish side and the subscribe side; the effective QoS for delivery to a subscriber is the lower of the two. The trade-off is reliability versus latency, bandwidth, and broker load.
| QoS | Name | Handshake | Delivery guarantee | Duplicates possible? | Best for |
|---|---|---|---|---|---|
| 0 | At most once | PUBLISH (fire and forget) | None; message may be lost if the link drops | No | High-rate, non-critical telemetry where the next sample arrives soon (temperature trend, vibration stream) |
| 1 | At least once | PUBLISH then PUBACK | Guaranteed delivery, but may arrive more than once | Yes; the consumer must be idempotent | Most SCADA tag updates, energy counters, alarms where a duplicate is harmless |
| 2 | Exactly once | PUBLISH, PUBREC, PUBREL, PUBCOMP (4-way) | Guaranteed exactly one delivery | No | Critical commands, billing-grade meter readings, totalisers where a double-count is unacceptable |
Practical guidance: do not default everything to QoS 2. The four-message handshake roughly quadruples broker traffic per message and adds round-trip latency, which matters on constrained cellular or LoRa backhaul. For most plant telemetry, QoS 1 with idempotent consumers is the sweet spot. Reserve QoS 2 for control writes and for counters where exactly-once semantics are genuinely required, such as a revenue-grade Modbus power meter feeding a billing system.
Retained messages
By default a subscriber only receives messages published after it connects. If a slow-changing topic like plant1/utilities/line3/pump_p101/status only publishes when the state actually changes, a dashboard that connects mid-shift would show nothing until the next change. Setting the retain flag tells the broker to store the last message on that topic and immediately deliver it to any new subscriber. There is exactly one retained message per topic; each new retained publish overwrites the previous one. To clear it, publish a zero-length payload with the retain flag set.
Use retain for last-known-value state (equipment status, setpoints, configuration) so any new client gets an instant snapshot. Do not retain high-frequency streaming telemetry, or new subscribers will receive a stale reading that looks current.
Last Will and Testament, keepalive
When a client connects it can register a Last Will and Testament (LWT): a topic, payload, and QoS that the broker publishes automatically if that client disconnects ungracefully. A gateway might set an LWT of offline on plant1/utilities/gateway01/state, and publish online (retained) itself on connect. Now any consumer can tell at a glance whether the gateway is alive, which is essential for trustworthy SCADA status.
The broker detects a dead client using the keepalive interval negotiated at connect time. If no packet (not even a PINGREQ) arrives within 1.5x the keepalive period, the broker considers the client gone and fires its LWT. A common setting is 60 seconds, giving roughly 90 seconds to declare a client offline. Shorter keepalives detect failures faster but add idle ping traffic, which matters on metered links.
Security: TLS and authentication
MQTT runs over plain TCP on port 1883 by default, which sends credentials and payloads in clear text. For any production IIoT system, run MQTT over TLS on port 8883. This encrypts the channel and, with client certificates (mutual TLS), authenticates each device cryptographically. At minimum, enable username and password authentication and disable anonymous access on the broker. Layer on topic-level access control lists (ACLs) so a given gateway can only publish under its own site/area branch and cannot subscribe to control topics it has no business reading. Defence in depth (TLS for the channel, credentials or certs for identity, ACLs for authorisation) keeps a single compromised device from exposing the whole plant.
MQTT versus OPC-UA
MQTT and OPC-UA are often compared, but they solve different problems. MQTT is a transport and messaging pattern: lightweight, broker-centric, excellent for many-to-many telemetry over unreliable WAN links, but it carries no built-in data model, so meaning lives in your topic convention or in an overlay like Sparkplug B. OPC-UA is a full information-modelling framework with typed nodes, browsable address spaces, and rich security, traditionally client/server and heavier on the wire. The two increasingly coexist: OPC-UA defines the semantic model inside the plant while MQTT (or OPC-UA PubSub over MQTT) handles efficient cloud transport. For greenfield IIoT data collection feeding analytics, MQTT plus a clear namespace is usually the faster path; choose OPC-UA where deep interoperability and standardised typing between automation vendors are the priority.
Frequently Asked Questions
Is MQTT secure enough for industrial control?
The protocol itself has no mandatory security, so security is your responsibility. With TLS on port 8883, client certificates or strong credentials, broker ACLs, and a hardened broker, MQTT is suitable for industrial telemetry and supervisory control. Avoid plain port 1883 and anonymous access in production.
Should I use QoS 1 or QoS 2 for SCADA tags?
Use QoS 1 for the vast majority of tag updates and make your consumers idempotent so an occasional duplicate is harmless. Reserve QoS 2 for control commands and exact counters (such as billing-grade energy totals) where a double-delivery would corrupt the result. QoS 2 costs significantly more broker traffic and latency.
How does MQTT compare to a Modbus polling architecture?
Modbus is request/response and master-driven; a SCADA master must poll each slave on a fixed cycle. MQTT is report-by-exception and publisher-driven, so devices send data only when it changes or on a chosen interval, cutting bandwidth and improving scalability. In practice a Modbus-to-MQTT gateway bridges the two worlds, polling serial devices locally and publishing the results upstream.
Do I need an edge device to use MQTT?
Not always, but it helps. Native MQTT PLCs can publish directly, yet most installed equipment speaks Modbus or other fieldbuses, so an edge gateway is needed to translate and buffer data. Understanding where that logic belongs is covered in our comparison of edge gateway versus PLC versus RTU, and the published data then feeds dashboards and AI industrial analytics.
MQTT rewards a few good decisions made up front: a clean site/area/line/device/metric namespace, QoS chosen per topic rather than globally, retained last-known-values for state, an LWT on every gateway, and TLS with ACLs from day one. Get those right and you have a telemetry backbone that scales from a single line to a whole plant. To see how this fits a full system architecture, explore SURIOTA’s Internet of Things services.