MQTT: How the Protocol Behind AGV Communication Works
How MQTT works: publish/subscribe, brokers, topics and wildcards, QoS levels, retained messages, and last will. Including how it compares to OPC UA and REST.
Why MQTT Shows Up in Every AGV Project
The moment an AGV project turns technical, MQTT enters the conversation. VDA 5050 is built on it, practically every fleet manager ships with an MQTT broker, and the IT team receives a requirements list full of ports, certificates, and topic names. What MQTT actually is and how it works is rarely part of that list.
This article explains the protocol from the ground up: how publish/subscribe works, what a broker does, how topics are structured, what the QoS levels really guarantee, and which mechanisms let a fleet manager notice within seconds that a vehicle has gone offline.
Related reading: VDA 5050 describes what data is exchanged between fleet manager and vehicle. VDA 5050 Message Flow shows the concrete topics and payloads. Fleet Manager as SaaS covers where the broker runs. This article explains the protocol itself, independently of VDA 5050.
What MQTT Is
MQTT is a lightweight publish/subscribe messaging protocol that runs on top of TCP. It was created in 1999 by Andy Stanford-Clark (IBM) and Arlen Nipper (then at Arcom) to transmit readings from oil pipelines over expensive and unreliable satellite links.
That origin explains exactly the properties that make MQTT attractive for vehicle fleets today:
- Minimal overhead. The fixed header of an MQTT message is two bytes. For comparison, the headers of a single HTTP request typically run to several hundred bytes.
- Tolerance for unstable links. Session handling, redelivery, and a defined offline mechanism are part of the protocol, not of the application.
- No need for simultaneous availability. Sender and receiver never have to be online at the same time, and they do not even know about each other.
MQTT 3.1.1 has been an OASIS standard since 2014 and was additionally standardized as ISO/IEC 20922 in 2016. MQTT 5.0 followed in 2019. Both versions are found in the field today.
Publish/Subscribe Instead of Request/Response
The decisive difference from a classic interface is who takes the initiative. With request/response, a client actively asks and waits for an answer. Anyone who wants to know the state of 30 vehicles asks 30 times, over and over, and learns about changes at the earliest on the next round.
With publish/subscribe, each participant instead registers with the broker to say what it is interested in. Whoever has something to report sends it once to the broker, which distributes it to all matching recipients the moment it happens.
This produces three kinds of decoupling that make the difference in practice:
Space
Publishers and subscribers know neither the address nor the number of their counterparts. A new vehicle joins without anything being configured on the fleet manager.
Time
Both sides do not have to be connected simultaneously. The broker bridges short outages, provided session and QoS settings are chosen accordingly.
Synchronization
Nobody blocks waiting for a reply. Sending and receiving run independently, which is decisive at hundreds of messages per second.
The Three Building Blocks
Broker
The only server component. It accepts connections, manages subscriptions, and forwards every message to all matching subscribers. It does not interpret the content.
Client
Anything that connects: the fleet manager, every AGV, a dashboard, a gateway. A client can publish, subscribe, or both. There is no privileged role.
Topic
The address of a message. A freely chosen string structured with slashes. There is no registration: a topic exists as soon as someone publishes to it.
Topics and Wildcards
A topic is a UTF-8 string, structured hierarchically with /. Structure and naming are defined by the application, not by the protocol:
plant1/hall2/agv/AGV-0017/position
plant1/hall2/conveyor/CV-003/status
Subscribers can work with two wildcards:
| Wildcard | Meaning | Example | Matches |
|---|---|---|---|
+ |
exactly one level | plant1/+/agv/+/position |
Positions of all AGVs in all halls of plant 1 |
# |
all remaining levels | plant1/hall2/# |
Everything below hall 2, at any depth |
The # may only appear at the end of a filter. Wildcards apply to subscribing only: publishing always targets a concrete, fully spelled-out topic.
Two conventions have proven themselves in projects. Topics do not start with / and contain no spaces, and the hierarchy runs from general to specific so that wildcard subscriptions produce meaningful slices. Topics starting with $ (such as $SYS/) are reserved for broker-internal statistics.
VDA 5050 applies exactly this principle with its fixed hierarchy interfaceName/majorVersion/manufacturer/serialNumber/topic. The fleet manager subscribes to all vehicle states with a single filter, while each AGV only listens to topics carrying its own serial number.
A Connection, Step by Step
MQTT defines a manageable number of packet types. Knowing them is enough to read a network capture and narrow down connection problems yourself:
| Packet | Direction | Meaning |
|---|---|---|
CONNECT |
Client → Broker | Connection request carrying client ID, credentials, keep-alive, session behavior, and an optional last will |
CONNACK |
Broker → Client | Acceptance or rejection, plus whether an existing session is being resumed |
SUBSCRIBE |
Client → Broker | List of topic filters with the requested QoS level |
SUBACK |
Broker → Client | Confirmation per filter, including the QoS actually granted |
PUBLISH |
both directions | The actual message: topic, flags, and payload |
PUBACK, PUBREC, PUBREL, PUBCOMP |
both directions | Acknowledgements for QoS 1 and QoS 2 |
PINGREQ, PINGRESP |
Client ↔ Broker | Sign of life within the keep-alive interval |
DISCONNECT |
Client → Broker (also the reverse in 5.0) | Clean end of the connection. The last will is not sent in this case |
A typical sequence when a vehicle starts up: CONNECT with a last will on its own status topic, CONNACK, SUBSCRIBE to its own order topic, SUBACK, then a continuous PUBLISH of its own state, interrupted by PINGREQ whenever there is nothing to send.
The QoS Levels
Quality of service defines how much effort sender and broker invest to make a message arrive. The level is chosen per message when publishing and per filter when subscribing:
| Level | Guarantee | Handshake | Typical use |
|---|---|---|---|
| QoS 0 | at most once | PUBLISH |
High-frequency position and sensor data where the next message follows within milliseconds anyway |
| QoS 1 | at least once | PUBLISH → PUBACK |
Orders, alarms, connection status. Anything that must arrive and where a duplicate is tolerable |
| QoS 2 | exactly once | PUBLISH → PUBREC → PUBREL → PUBCOMP |
Non-idempotent or billing-relevant commands. Rarely needed in AGV settings |
Higher levels cost round-trips and state on both sides. That is why VDA 5050 deliberately uses QoS 0 for order, state, and visualization, and only raises the connection topic to QoS 1, because a lost offline notification is not healed by the next message.
Retained Messages
Normally a subscriber only sees what is published after it subscribed. Connect at 10:00 and you learn nothing about the message sent at 09:59.
The retained flag changes that: the broker stores the last message published with this flag per topic and delivers it to every new subscriber immediately. This suits states that hold over time, such as configuration values or the online status of a vehicle. It does not suit events.
Last Will and Keep-Alive
Together these two mechanisms answer the question asked most often in practice: how does the fleet manager know that an AGV is gone?
The last will is registered as early as CONNECT, long before it is needed. The client hands over topic, payload, QoS, and retained flag of a message the broker should publish if the connection is not terminated cleanly. A power loss on the vehicle, a dropped WiFi link, or a crashed process trigger it; a regular DISCONNECT does not.
The keep-alive is the client's promise to send something at least every N seconds, a PINGREQ if nothing else. If the broker hears nothing for one and a half keep-alive intervals, the client counts as dead and the last will fires.
That leads to a design decision worth making deliberately:
| Keep-alive | Outage detected after | Assessment |
|---|---|---|
| 10 s | 15 s | Quick to react, slightly more baseline load on the network |
| 30 s | 45 s | The usual compromise for AGV fleets |
| 60 s | 90 s | Economical, but a minute of uncertainty about a halted vehicle |
| 300 s | 7.5 min | Effectively unusable for mobile vehicles |
MQTT 5.0 adds a will delay interval: the last will is published only after a waiting period. If the client reconnects before that, it is dropped. This defuses the short radio gaps during WiFi roaming that would otherwise be reported as a vehicle outage every time.
Sessions: What the Broker Remembers
When connecting, the client decides whether it wants a fresh session or wants to resume an existing one. In MQTT 3.1.1 this happens through the clean session flag:
Clean Session = true: the broker discards everything previous. Subscriptions must be set again, buffered messages are lost.Clean Session = false: the broker keeps subscriptions and buffered QoS 1 and QoS 2 messages for that client ID. After a reconnect, delivery continues.
MQTT 5.0 separates this more cleanly into clean start (begin with a fresh session) and session expiry interval (how long the session is kept after disconnecting).
The anchor of that session is the client ID. It must be unique per broker. If two clients connect with the same ID, the broker disconnects the older connection. If that one immediately reconnects, a loop forms in which the two keep evicting each other. The symptom is vehicles flipping between online and offline every second.
MQTT 3.1.1 or MQTT 5.0
3.1.1 is still the most widely deployed version and entirely sufficient for an AGV project. 5.0 is backward compatible in concept but not at the protocol level: client and broker must agree on the same version.
| New in 5.0 | Benefit |
|---|---|
| Reason codes | Rejections and errors are explained in machine-readable form instead of appearing as a dropped connection |
| User properties | Free key-value pairs in the header, for correlation IDs or tracing |
| Topic aliases | Long topic names are mapped to a number per connection, which saves bandwidth |
| Shared subscriptions | Multiple instances share one subscription stream via $share/group/topic, the basis for load balancing |
| Message expiry | Messages expire after a defined time instead of being delivered stale |
| Session expiry | An explicit session lifetime instead of the binary clean session flag |
| Will delay | The last will fires only after a waiting period and therefore skips short radio gaps |
| Request/response | Response topic and correlation data are standardized instead of reinvented in every project |
In practice the vehicle fleet decides: the version has to be supported by every vehicle that will connect to the broker. It therefore belongs in the specification document, not in the commissioning phase.
Security
MQTT brings no encryption of its own. Security comes from combining TLS, authentication, and authorization at the broker:
Transport encryption
MQTT over TLS (MQTTS) on port 8883. The unencrypted port 1883 belongs closed in production. MQTT over WebSockets has no reserved port; 8083, 8084, or 443 are common.
Authentication
Username and password or, more robustly, client certificates with mutual TLS authentication. Every client gets its own credentials, never shared ones.
Authorization
ACLs at the broker define who may publish and subscribe on which topic. A vehicle is granted rights on its own namespace only, never on anyone else's.
Client IDs
A documented naming convention prevents collisions and keeps logs readable. Tying the ID to a serial number or asset tag works well.
The payload itself stays untouched by all of this. Anyone who needs confidentiality beyond the broker has to encrypt the payload additionally at application level.
Choosing and Sizing a Broker
| Broker | Character |
|---|---|
| Eclipse Mosquitto | Very lightweight, written in C, single node. The classic choice for a single site |
| HiveMQ | Java, clusterable, enterprise features and commercial support |
| EMQX | Erlang, clusterable, designed for very large client counts |
| VerneMQ | Erlang, clusterable, open source |
| NanoMQ | Particularly small footprint, intended for edge devices and gateways |
| Managed cloud | Operations outsourced, at the cost of depending on the internet connection |
On sizing: one AGV produces roughly one to five messages per second across all topics, dominated by high-frequency position data. A fleet of 50 vehicles therefore lands at a few hundred messages per second, which is uncritical for every broker listed above. The bottleneck in AGV projects is practically never the broker, it is WiFi coverage.
Two points still belong in the selection: whether the broker supports the required MQTT version and QoS level (not every managed broker offers QoS 2), and whether it can be clustered for high availability. Where the broker then runs is covered in Fleet Manager as SaaS.
MQTT, OPC UA, or REST?
These protocols coexist inside a plant. The question is not which one wins, but which one fits which leg of the journey:
| Criterion | MQTT | OPC UA | REST over HTTP |
|---|---|---|---|
| Communication pattern | Publish/subscribe via a broker | Client/server, plus a PubSub variant | Request/response |
| Data model | None, raw bytes in the payload | Rich, typed information model | None, usually JSON by local convention |
| Overhead | Very low | High | Medium to high |
| Event driven | Yes, natively | Yes, through subscriptions | No, requires polling or webhooks |
| Decoupling of participants | High | Medium | Low |
| Typical role in the plant | Vehicle and device communication, VDA 5050 | Machine and line integration with semantics | ERP, WMS, and web interfaces |
- MQTT, when many participants exchange state in an event-driven way and the connection is not guaranteed to be stable. That is precisely the AGV case.
- OPC UA, when machine data with meaning is transported and a shared information model matters more than low overhead.
- REST, when one system queries or triggers another on purpose, such as confirming a transport order back to the warehouse management system.
A typical setup combines all three: the ERP or WMS talks REST to the fleet manager, the fleet manager talks MQTT and VDA 5050 to the vehicles, and line equipment sits alongside on OPC UA. What the upper layer looks like is described in SAP Integration with Your AGV System.
Common Pitfalls in AGV Projects
- Duplicate client IDs. Two clients with the same ID keep kicking each other off the connection. The symptom is vehicles flipping between online and offline every second.
- Treating QoS as an end-to-end guarantee. The level is negotiated per hop, and the second hop uses the minimum of publish and subscription QoS.
- Subscribing to
#. An analysis tool or dashboard that subscribes to everything pulls the entire traffic onto itself. In production systems this belongs blocked by ACL. - Stale retained messages. After rebuilds or decommissioned vehicles, old states remain, and a new subscriber takes them for current.
- Keep-alive set too generously. The value directly determines how long a failed vehicle stays unnoticed. It is a project decision, not a default to accept.
- WiFi roaming not considered. Every handover between access points can drop the TCP connection. Without fast roaming (802.11r, k, v) and persistent sessions, gaps appear in the data.
- No monitoring. Message rate, connection drops, and broker load belong on a dashboard. Otherwise a slowly growing problem only surfaces once the fleet has stopped.
Commissioning Checklist
- [ ] Broker product and deployment location decided
- [ ] MQTT version (3.1.1 or 5.0) agreed with every supplier
- [ ] Client ID convention documented and unique across the project
- [ ] TLS active on port 8883, port 1883 closed in production
- [ ] Individual credentials or certificates per client, none shared
- [ ] ACLs restrict every client to its own topic namespace
- [ ] Keep-alive defined and the resulting outage detection time accepted
- [ ] Last will defined on a status topic, retained behavior clarified
- [ ] Clearing strategy for retained messages documented
- [ ] Monitoring in place for message rate, connections, and broker load
- [ ] WiFi coverage and roaming validated on all vehicle routes
Takeaways
- MQTT decouples the participants: publishers and subscribers do not know each other, and the broker is the only server component and therefore the single integration point IT has to secure.
- Topics are freely designed hierarchies. The wildcards
+and#turn them into flexible subscriptions, but they belong fenced in by ACLs. - QoS applies per connection hop, not end to end. The effective level is the minimum of publish and subscription QoS.
- Last will and keep-alive determine how fast a vehicle outage is noticed. That is a deliberate design choice, not a default.
- MQTT transports bytes without meaning. The semantics come from the layer above, in intralogistics usually from VDA 5050.
Knowing these mechanisms changes how you read a supplier specification: topics, QoS levels, and keep-alive values stop being formalities and become figures with direct consequences for the reaction time and diagnosability of the installation.
The specifications for both versions are freely available at mqtt.org.
AGVHub