MQTT vs OPC UA for Industrial IoT: a practitioner's guide from the plant floor
If you are building software that reads data from machines, you will meet the same question again and again. Should you use MQTT or OPC UA? It is usually framed as an either or choice, and people can hold firm views on it, even though it is really a technical decision with a technical answer.
The honest answer is that this is the wrong question. In most real systems you end up using both, each in the place where it works best. This article explains what these two protocols are, how they work, and where each one belongs. The examples are kept simple on purpose, so you can follow along even if this is new to you.
Let us start with the older of the two.
OPC UA: the standard of the shop floor
OPC UA stands for Open Platform Communications Unified Architecture. It was released in 2008 and grew into a common language that industrial equipment uses to share data. Many major automation makers build support for it directly into their controllers, so you will find it across a lot of modern plant hardware.
How it works: client and server
OPC UA mostly works in a client and server style. A server sits on a machine, for example a PLC. A client, such as a SCADA system, opens a connection to that server and then requests values on a fixed cycle. It asks for the same readings again and again, often several times a second, and takes whatever comes back each time. This repeated requesting has a name. It is called polling.
Figure 1: OPC UA keeps asking the machine for data (polling). MQTT only sends data when something changes (publish and subscribe).
Why people like it: data that explains itself
The best part of OPC UA is that it does not just send a number. It sends the number together with everything that explains what the number is.
Think about the difference. An older protocol like Modbus gives you something like 40001 = 75. That is a value at an address, and nothing more. You have no idea what it means. Is 75 a temperature, a pressure, a speed? In Celsius or Fahrenheit? You need a separate sheet, kept by a person, that tells you "address 40001 is motor temperature in Celsius."
OPC UA gives you the whole picture instead:
- Name: Motor1.Temperature
- Value: 75
- Unit: Celsius
- Type: Float
- Belongs to: Pump Station A, Motor 1
The data describes itself. A new application can connect, move through the server like folders on a computer, and understand the machine without anyone handing it a manual. It can also show how the parts fit together. For example, it can say that a cooling unit contains a compressor, the compressor has a motor, and that motor reports both a temperature and a running current. So OPC UA carries two things at once: the meaning of each value, and the structure that links the values into a picture of the real equipment.
Figure 2: A bare Modbus register tells you nothing. An OPC UA value carries its own meaning.
Where it gets heavy
OPC UA has one weakness. Because it keeps polling, it can be chatty. Sending all that traffic across a cellular link or a weak Wi-Fi connection to the cloud can eat up your bandwidth fast.
There is also a scaling problem, and it grows quietly. In the client and server style, every application that wants data has to open its own direct connection to every machine it reads from. Say a plant starts with one dashboard reading thirty machines. Later someone adds a maintenance tool, then an energy report, then an AI model. Each new tool has to connect to all thirty machines on its own. Four tools across thirty machines is already one hundred and twenty separate connections to set up, secure, and keep alive. Every one of them is a link that can quietly fail, and the count climbs each time you add a tool or a machine.
Figure 3: In the client and server style, each application connects to each machine on its own, so the number of connections multiplies fast.
MQTT: a lighter way to move data
MQTT was invented back in 1999 to monitor oil pipelines over slow and expensive satellite links. Every byte cost money, so it was built to be light.
How it works: publish and subscribe
Instead of one client asking one machine over and over, MQTT uses a middleman called a broker. Devices push data to the broker only when a value actually changes. This is called report by exception. Applications that want the data simply tell the broker, "let me know when the temperature on Machine 1 changes."
This is the big idea: the machine does not know or care who is listening. It just publishes. Anyone interested subscribes through the broker.
Why this saves bandwidth
Bandwidth just means how much data you push across the network. Picture the network as a pipe and the data as water flowing through it.
With OPC UA polling, a tank that sits at 75 degrees all day still gets asked for its value many times per second, and answers every time. That can be hundreds of thousands of messages for a number that never moved.
With MQTT, the same tank stays quiet. It only speaks up when the value changes, say from 75 to 76. Instead of hundreds of thousands of messages, you send a handful. Far less water in the pipe. On a cellular gateway at a remote site, this is the difference between a cheap connection and an expensive one.
Scaling is easy
Adding a new application to MQTT is simple. A new AI tool just subscribes to the broker. The machine does not even know the new tool exists. You can connect many applications without touching the machines at all.
Knowing when a machine goes dark
MQTT has a clever feature called Last Will and Testament, or LWT. It solves a real problem.
Because MQTT only sends data when a value changes, silence is confusing. If a sensor has not sent anything for ten minutes, you cannot tell which of these is true:
- Everything is fine and the value simply did not change, or
- The machine lost power and cannot send anything at all.
From the outside, both look the same. That is dangerous.
LWT works like a real will. When a device connects, it hands the broker a message in advance and says, "if I disconnect suddenly, send this on my behalf." For example, Machine1/status = OFFLINE. The broker holds that message. As long as the device stays in touch, nothing happens. The moment the connection drops, the broker sends out the offline message to everyone.
How does the broker know the device is still alive? The device promises to check in within a set time, called keep alive. If it has real data, that counts. If not, it sends a tiny ping just to say "still here." If the broker hears nothing at all for a grace period, it decides the device is gone and fires the will.
Figure 4: The device checks in with small heartbeats. When the heartbeats stop, the broker announces it is offline.
Here is a real example. A temperature sensor in a cold store loses power. Without LWT, the dashboard keeps showing the last reading, frozen at 4 degrees, and the operator thinks the room is fine. With LWT, the broker immediately announces that the sensor is offline, so the dashboard can show "sensor lost, status unknown" instead of a stale number that looks healthy. In a cold store, knowing that a sensor went quiet is itself important, because silence could be hiding a temperature problem.
The catch with plain MQTT
MQTT has no rules about what you put inside a message. Think of it as a courier that will deliver any box you hand over without checking what is inside. That freedom cuts both ways. You can send clean, well labelled data, or you can send a jumble, and MQTT treats them the same. Early industrial projects paid for this, because every team formatted their data differently, and engineers lost weeks lining it all up by hand.
A quick word on message size
You might hear that MQTT is tiny and everything else is heavy. There is a popular chart that shows the bytes each protocol adds to a single data point.
Figure 5: The bytes each protocol adds. The left bars show bare protocol size. The right side shows what a real, labelled reading actually costs.
The numbers usually look like this: plain MQTT around 2 bytes, Sparkplug B around 20, OPC UA around 150, and HTTP around 800. At first glance MQTT looks like the clear winner.
But there is a trap here, and it is worth understanding. Those 2 bytes are only the empty envelope. They measure the protocol on its own, with no real content. In real life you never send an empty value. You send a value with a name, a timestamp, and a type, so you actually know what it is.
The moment you do that honestly in plain MQTT, you reach for JSON, which is wordy. A single labelled reading in JSON can be around 65 bytes. Sparkplug B carries the same information in about 20 bytes. So for a real reading, Sparkplug B is smaller than plain MQTT with JSON. The bare "2 versus 20" picture is misleading once you add the structure a real system needs.
Sparkplug B: structure on top of MQTT
To fix the "anything goes" problem of plain MQTT, the Eclipse Foundation created Sparkplug B. It is a set of rules that sit on top of MQTT.
Sparkplug B does two things. First, it forces a strict format called Protocol Buffers, or protobuf. Second, and this is the part people miss, it defines one fixed format that everyone uses.
Why does that create predictability? Protobuf by itself just means you need a schema, a fixed definition of the fields. Sparkplug B goes further and publishes the exact schema for everyone. So every Sparkplug B device on earth describes a reading the same way, with the same fields: a name, a type, a timestamp, a value, and an order number. It also defines clear messages for when a device comes online (a birth message) and goes offline (a death message).
Figure 6: Sparkplug B does not replace MQTT. It adds a fixed structure on top of it.
The result is that MQTT gets back the self describing quality that OPC UA always had, while keeping the light and scalable nature of publish and subscribe. A new subscriber can connect and understand the data without a manual.
One honest note so you do not overclaim it. Sparkplug B gives you structure, consistent fields and types and clear online and offline states. But it is lighter than OPC UA's full model. OPC UA can describe deep relationships between parts. Sparkplug B is flatter. It is close to OPC UA in spirit, not identical.
What about OPC UA Pub/Sub?
You may have heard that OPC UA now has its own publish and subscribe mode, so maybe it can replace MQTT. The short answer is: not yet, in practice.
OPC UA Pub/Sub is a newer part of the standard. It lets OPC UA publish data outward when it changes, instead of only being polled. It can run in two ways. In one, it publishes over an MQTT broker, so it actually rides on top of MQTT rather than replacing it. In the other, it sends data directly over the local network with no broker, which suits fast machine to machine traffic on a factory floor.
It would be wrong to dismiss this as a passing trend. The opposite is true. The spec has existed since 2018, and in 2026 it became a European standard (EN IEC 62541-14). The largest standards body in this space sits behind it, and several toolkits and broker bindings already exist. The catch is adoption, not credibility. Years after it was published, it is still almost invisible in real production sites, and most vendors still ship OPC UA in the old client and server mode. So the honest read is simple: a real standard that has been waiting for its ecosystem since 2018.
It also helps to know that the wider industry is not trying to pick a single winner. The common pattern in 2026 is to use both, OPC UA where shared meaning matters and MQTT or Sparkplug B where scale and fan-out matter. Keep an eye on OPC UA Pub/Sub, but do not build your whole system on it today.
The part that matters most: security
Now to the most useful idea in this whole topic. People argue about which protocol is more secure. That argument mostly misses the point. What keeps an attacker out is how you wire the connection, not which protocol you chose.
To see why, you need two simple ideas.
Transport layer and application layer
Imagine sending a private letter through the post.
You could hire an armoured truck so nobody can grab the letter on the way. That protects the journey. This is the transport layer. The common tool here is TLS, the same thing that puts the padlock in your web browser.
Or you could write the letter in a code that only the receiver can read, and sign it so they know it is really from you. That protects the letter itself, no matter how it travels. This is the application layer.
Figure 7: Transport security protects the delivery channel. Application security protects the message itself.
Here is how the two protocols compare. MQTT leans on TLS, so it secures the pipe between the device and the broker. The message inside is not separately locked. OPC UA builds security into the message itself. It signs and encrypts the actual data, not just the pipe. This is why people say OPC UA is more secure. Its protection is deeper. The important thing, though, is that once both are set up properly, this difference stops mattering much in practice.
Certificates, in plain terms
A certificate is a digital ID card. It proves "I am who I say I am." When two machines connect, they show each other their certificates and check that the other side is genuine before any data flows. It is like two people checking passports before doing business. This also hands over the keys needed to encrypt the conversation.
Who issues these ID cards? On the public web, trusted companies called Certificate Authorities do it, which is why your browser trusts a website without you knowing the site. Inside a closed factory network, you usually run your own internal authority and issue your own certificates. Think of it as a private club making its own membership cards, valid only inside your walls. For a factory this is normal, and often better, because you do not want your shop floor depending on the public internet to approve a sensor.
The decision that actually protects you
Here is the point that matters most. The critical security decision is about architecture, not protocol. What actually protects you is using an outbound only gateway.
Picture two sides. On one side is the factory network, where the PLCs and sensors live. On the other side is the cloud, where the dashboards and AI live. The dangerous question is: who is allowed to start a connection?
If the cloud is allowed to reach into the factory, there is an open door in the factory firewall. An attacker on the internet can find that door and push on it. Every open inbound door is a way in.
An outbound only gateway flips this. The edge device is set up so it can only dial out, like making a phone call. It reaches out to the cloud whenever it wants, but nothing on the outside is allowed to dial in. The factory firewall has no open inbound doors at all. There is simply no door for an outsider to push on.
Figure 8: An outbound only gateway can dial out to the cloud, but nothing from outside can reach into the plant.
This beats protocol choice every time. You could run perfect OPC UA encryption, but if you left an inbound door open so the cloud could poll your PLC, you created a way in that no encryption fixes. A simpler MQTT setup that only dials out is much harder to attack, because there is no way in to begin with.
This is not just one writer's opinion. In 2026 an industry group focused on industrial security published a joint statement making the same point, that secure communication is not decided by the protocol alone, but by how the system is deployed. So this is the mainstream view, not a fringe take.
At Zebblo we follow two simple rules for exactly this reason. Our edge connection is outbound only, so there is no inbound door. And our gateway is read only by default, so even if someone somehow got in, it can only watch the plant, never send a command. It cannot open a valve or trip a breaker. Together these let us tell a plant team a clear and honest thing: our box cannot be reached from outside, and even from inside it only reads. That is a stronger claim than arguing about which protocol has deeper encryption.
One honest limit, so the story stays straight. Outbound only stops uninvited traffic from the outside. It does not make everything perfectly safe. The data still lands in your cloud, so the cloud side and the gateway's own login still need protecting. It removes the biggest risk. It does not remove every risk.
So which one do you use?
You do not have to choose. A practical setup uses both, each where it fits.
For fast control on the local factory floor, where a machine must react in a few milliseconds, OPC UA or a fieldbus protocol is the right tool. It is built for tight, local, machine to machine work.
For pulling data from many machines across many sites into a central place for dashboards, reporting, and AI, MQTT with Sparkplug B is the better fit. It is light, it scales, and it handles weak connections well.
The common modern pattern is an edge gateway that speaks both. It reads from the machines locally using OPC UA or Modbus, adds the meaning and structure, and then publishes clean, light MQTT messages up to the cloud.
A note from the field
One last point. A lot of the popular writing on this topic is produced by protocol and platform companies, and it tends to assume a clean, modern, greenfield setup. Real sites are often messier than that. On many plant floors, including a lot of the older brownfield ones across India and elsewhere, the tidy OPC UA path is simply not there to plug into. Many plants run on SCADA systems that write to a SQL database, and the practical bridge is to read from that database, not from OPC UA directly. The register maps are messy, and the wiring on the RS485 lines causes more trouble than the protocol debate ever does. The protocol matters less than the boring reality of getting a stable, read only, outbound only connection that a plant team trusts. That trust, more than any protocol, is what gets a project from a pilot to a running system.
If you are weighing these choices for your own plant, the short version is this. Use OPC UA where you need rich, local, structured control. Use MQTT and Sparkplug B to move data out to the cloud at scale. And spend your real attention on the architecture, read only and outbound only, because that is what keeps the whole thing safe.