Recent MQTT vs. OPC UA comparisons repeat a handful of claims about deterministic, bidirectional feedback loops that don't hold up under technical scrutiny. This post corrects the record, shows the MQTT 5 properties and topic patterns that handle the cases critics point to, and closes with a practical starting checklist.
- A new MQTT topic doesn't require touching a server's information model the way an OPC UA address space change often does. That freedom still has to live inside a governed namespace, not outside one.
- MQTT is push-based. Delays shown in side-by-side demos usually come from application logic, not the protocol, and MQTT 5's request/response properties handle deterministic feedback loops natively.
- OPC UA's client-server model fits orchestration. MQTT's publish/subscribe model fits choreography. Neither is a downgrade of the other; they solve different coordination problems.
Who this blog is for: OT/IT architects and engineering leads who keep running into MQTT vs. OPC UA comparisons that don't match what the protocols actually do, and who want working topic patterns and configuration guidance, not just a technically precise argument.
If you've sat through an MQTT vs. OPC UA comparison in the last year, you've probably heard some version of this: OPC UA handles real-time control and structured data, while MQTT is great for scale but can't really do deterministic, bidirectional actions without extra work. Add a new signal, and MQTT supposedly needs new topics and new systems bolted on. OPC UA, so the story goes, just needs a variable.
That framing shows up in webinars, vendor comparisons, and no shortage of LinkedIn threads. Some of it is fair. Some of it isn't. A handful of specific claims about MQTT, particularly around command and feedback loops, misrepresent how the protocol actually behaves under the hood.
This isn't another "which protocol wins" post. It's a closer look at where the comparisons get the mechanics wrong, and the framework that actually explains why OPC UA and MQTT behave so differently: orchestration versus choreography.
This assumes you're already building toward the kind of real-time data backbone we cover in Connect: Building a Real-Time Data Backbone for Data Accessibility, the first stage of what we call the Dynamic Intelligence Loop: connect, contextualize, analyze, act. That piece lays out the architecture. This one zooms into the protocol-level claims that trip people up while you're building it.
Two protocols built for different jobs
OPC UA earns its reputation for good reasons. Its information model is rich and standardized: companion specifications like OPC UA for PackML or Machinery let a client connect to any conforming device and encounter the same structure, with no custom integration required. Its address space is self-describing, so a generic client can browse a server and understand what's available without external documentation. Its security model, built on certificate-based authentication with signed and encrypted sessions, is mature and well suited to machine-to-machine communication at the cell level, with granular authorization down to individual nodes. And a lot of shop-floor equipment ships with an OPC UA server out of the box.
MQTT wasn't built to compete with that. It was built to move state changes efficiently between producers and consumers who don't need to know about each other. A PLC publishes; it doesn't need to know who's listening or why. That loose coupling, combined with an event-driven publish/subscribe model instead of request/response, is what lets MQTT scale to tens of thousands of endpoints without connection count spiraling out of control.
We've covered the detailed, feature-by-feature version of this comparison before. What's worth revisiting here isn't the general case. It's a specific set of claims about MQTT's suitability for deterministic, production-facing feedback loops that keep resurfacing and don't hold up.
Where the comparisons get it wrong
"Extra topics" aren't extra system risk
The claim: tracking who received a command, whether it matched what was expected, and what happened next needs new topics and new systems in MQTT, adding fragility that OPC UA avoids because "it already has the variable."
In practice, it's closer to the reverse. A new MQTT topic is a namespace addition. Nothing on the broker needs to be registered, modeled, or provisioned before a client starts publishing to it. OPC UA doesn't work that way: exposing a new piece of information generally means changing the server's address space, and the OPC Foundation's own modeling guidance is explicit that this should happen through purpose-built methods, not ad hoc node creation, because generic node-management calls give a client no way to know where it's allowed to add or remove anything. Some servers don't support runtime address space changes at all; configuration only changes through the vendor's engineering tool.
That doesn't mean MQTT topics are a free-for-all. A new topic still needs to sit inside your existing namespace convention, not float outside it. The difference from OPC UA isn't whether structure matters. It's where that structure lives. In OPC UA, it lives in the server's information model, changed per device, per vendor. In MQTT, it lives in your namespace governance, defined once and enforced centrally. A well-organized topic tree makes that possible, but the tree by itself isn't the governance. That distinction is also what separates a plain MQTT topic hierarchy from a genuine Unified Namespace (UNS): a tree of topics is necessary, but it isn't sufficient on its own.
In practice, that convention might look like this for a single asset:
plant1/lineA/robot12/state
plant1/lineA/robot12/cmd/close-valve
plant1/lineA/robot12/cmd/close-valve/ackAdding the "close-valve" command means adding a leaf under an asset that already exists, not standing up a new system. The governance question is whether cmd and ack are modeled the same way across every asset and every site, not whether the leaf is allowed to exist in the first place.
MQTT doesn't poll, it pushes
The claim: deterministic, bidirectional actions, like closing a valve and confirming receipt, need to happen immediately, "not when a topic updates or the system polls." The implication is that MQTT is inherently too slow or indirect for this kind of exchange.
That's a mischaracterization of the protocol. MQTT is push-based: when a client publishes, the broker delivers to every subscriber right away. There's no polling built into MQTT at any point. Delays that show up in side-by-side demos usually come from the application logic wrapped around the protocol, extra processing nodes, custom flows, not from MQTT itself.
For genuine request/response semantics, MQTT 5 added Response Topic and Correlation Data as standard PUBLISH properties. A requester sets a response topic and attaches correlation data; the responder publishes its answer to that topic with the same correlation data, so the original sender can match replies to requests, even from multiple responders. That's native protocol support for the same transactional pattern these comparisons claim MQTT can't do without custom tooling. In code, wiring the two sides together is a few lines:
# Requester: publish a command with the response wired up
client.publish(
topic="plant1/lineA/robot12/cmd/close-valve",
payload=json.dumps({"cmd": "close_valve", "requestId": "8841"}),
qos=1,
properties=Properties(
response_topic="plant1/lineA/robot12/cmd/close-valve/ack",
correlation_data=b"8841",
),
)
# Responder: acknowledge on the response topic, same correlation data
client.publish(
topic="plant1/lineA/robot12/cmd/close-valve/ack",
payload=json.dumps({"status": "confirmed", "requestId": "8841"}),
qos=1,
properties=Properties(correlation_data=b"8841"),
)No polling loop, no separate acknowledgment system to build. Use QoS 1 or higher on both sides so a dropped command isn't silently lost, and skip retain on the command topic; a stale "close valve" sitting on the broker for the next subscriber is a hazard, not a convenience.
There's a second, complementary mechanism worth knowing: manual acknowledgment. Most MQTT client libraries send the QoS 1/2 protocol acknowledgment back to the broker as soon as a message arrives, regardless of what the application does with it next. Switching to manual acknowledge mode lets the application withhold that ack until it has actually finished processing the message: validated it, written it to a database, whatever "done" means for that consumer. If processing fails, the ack never goes out, and the broker redelivers. That ties MQTT's own delivery guarantee to business-layer success, not just network delivery. Response Topic and Correlation Data answer "what's the reply to my request." Manual acknowledgment answers "did the receiving system actually handle this correctly." Most MQTT 5 client libraries expose it as a subscription setting, not custom protocol work.
One distinction worth being precise about: this is about command and feedback loops at the application level, seconds down to low milliseconds, not hard real-time motion control. If you need microsecond-level determinism for synchronized drives, OPC UA paired with Time-Sensitive Networking is the right tool, and MQTT was never trying to compete there. Comparisons that conflate the two are arguing against a claim nobody serious is making.
It's also worth naming a pattern in how these demos get built. Many pit a finished OPC UA server feature against MQTT plus custom application logic. That's not a protocol-level comparison; it's a built-in feature against logic someone wrote for the demo. The equivalent OPC UA effort, standing up the server and modeling the address space to support it, just happens earlier and out of view.
Orchestration and choreography: the real question
This is what ties the previous two points together. OPC UA's client-server, request-response model fits orchestration: a central instance calls a method and expects an immediate, deterministic answer. That's a strong fit at the cell and machine level, where tight command-feedback loops matter and a single coordinator makes sense.
MQTT's publish/subscribe model fits choreography: independent components react to shared events without a central coordinator. That's the coordination style behind Event-Driven Architecture (EDA), and it's what lets loosely coupled systems scale across a plant or an enterprise without every new consumer needing a direct relationship with every producer.
Neither is a downgrade of the other. If a cell genuinely needs orchestration semantics, OPC UA delivers that natively, or you reach for MQTT 5's request/response properties described above. Both are deliberate choices, not compromises. The real question was never "what can the protocol do." It's "what coordination style does this layer of the architecture actually need."
That said, choreography only pays off if the events it coordinates are published somewhere consistent. Loose coupling built on an unstructured pile of topics doesn't scale any better than tight coupling did; it just fails less visibly. The reason MQTT's publish/subscribe model works at scale is the same reason a well-designed Unified Namespace matters: a shared, governed structure is what lets independent components find and trust the events they're reacting to.
A rough rule of thumb for picking between the two at a given layer:
| Situation | Lean toward | Why |
|---|---|---|
| One coordinator needs a guaranteed answer before the next step | Orchestration (OPC UA method, or MQTT 5 request/response) | Something has to know the outcome before proceeding |
| Several independent systems need to react to the same event | Choreography (MQTT publish/subscribe) | Adding a new consumer shouldn't require changing the producer |
| Producers and consumers are added or replaced on different schedules | Choreography | Loose coupling avoids a growing web of point-to-point calls |
Self-description isn't exclusive to OPC UA
The claim: catalogued, referenceable data with built-in self-description is something "only OPC UA" can offer.
At the level of a single server, that's true, and worth saying plainly. An OPC UA address space describes its own data model; a generic client can browse it without an external reference. MQTT doesn't do that at the protocol level, and it isn't trying to.
The functional equivalent on the MQTT side doesn't live in the protocol. It lives in a contextualization layer built deliberately on top of it: MQTT 5 user properties for lightweight cases, or a semantic layer like HiveMQ Pulse for something closer to what OPC UA gives you natively. Sparkplug follows the same logic: a payload and topic convention layered on top of MQTT, not a protocol feature, aimed at device-level interoperability on the shop floor rather than UNS-level governance. That's not a workaround; it's a different design choice that separates transport from context. At the scale of a single device, OPC UA's built-in self-description is genuinely less work upfront. At the scale of dozens of vendors and hundreds of device types, paying for self-description once, centrally, tends to cost less than paying for it per device, per manufacturer.
A minimal, consistent payload envelope does most of the work:
{
"value": 82.4,
"unit": "degC",
"quality": "GOOD",
"timestamp": "2026-08-03T10:15:30Z",
"schemaVersion": "1.0"
}Enforced across every publisher, that envelope answers the same question an OPC UA client answers by browsing the address space: what is this value, in what unit, and can it be trusted right now. The enforcement point is what matters. Leave the schema to individual teams and it drifts within a quarter; put it behind a schema registry or a governance layer like HiveMQ Pulse, and a new publisher either conforms or gets rejected before bad data reaches a consumer.
"OPC UA over MQTT" doesn't give you a Unified Namespace
The claim, or more precisely the implication: since OPC UA Part 14 can publish over MQTT, a separate MQTT/UNS strategy is redundant, because OPC UA already covers it.
Part 14 PubSub is real and useful for OPC-UA-native environments, but it isn't a substitute for a UNS. It moves the transport from TCP to MQTT while keeping OPC UA's own type system on the subscriber side, so the loose-coupling benefit of a UNS, where any consumer can read a topic without understanding a foreign server model, mostly disappears.
There's also a security trade-off that doesn't get much airtime. End-to-end message security across MQTT, including through third-party or public brokers, is only available with Part 14's UADP binary encoding. Switch to JSON, the encoding that actually resembles a readable UNS-style payload, and you're relying on MQTT's own transport and broker security instead. Put simply: you get OPC UA's security model in binary UADP, tightly coupled to OPC UA tooling, or you get UNS-compatible JSON without OPC UA's own message-level protection. Not both, for free, at the same time.
A UNS also depends on a topic structure that stays consistent across every source system, not only the ones speaking OPC UA. Part 14 brings its own address-space model to the exchange, and without an additional contextualization layer, that doesn't automatically translate into a shared structure. What you get is MQTT as transport. What a UNS needs is MQTT as an architectural principle.
Our own architecture whitepaper frames this as two complementary layers: a Unified Namespace for the hierarchical, event-driven view, and a semantic graph for the relationships a pure hierarchy can't express. Part 14 PubSub, done well, gets you transport. Neither of those two layers comes with it for free.
In practice, that means the bridge, whether it's an edge gateway or a broker-side OPC UA integration, should read from the server's address space and republish onto your existing topic convention using your existing payload contract, not stand up a second, OPC-UA-shaped namespace next to it. If Part 14 PubSub is already running upstream, treat it as one more source feeding the same UNS, not as the UNS itself.
A practical starting point
A few concrete choices carry most of the weight if you're building this now:
- Topic naming. Follow a consistent hierarchy, for example
enterprise/site/area/line/cell/asset/signal, and keep command and acknowledgment as siblings under the same asset rather than in a separate tree. - QoS and retain. Use QoS 1 or higher for commands; a lost command is a production incident. QoS 0 is fine for high-frequency telemetry, where the next value supersedes the last. Retain state topics so new subscribers get the current value immediately, and skip retain on one-off commands.
- Request/response wiring. Set Response Topic and Correlation Data on the command PUBLISH, and have the device or edge gateway echo the same correlation data back on the ack. Most MQTT 5 client libraries expose both properties directly, so this is configuration, not custom protocol work.
- Processing confirmation. Where you need to know a message was actually handled, not just delivered, turn on manual acknowledgment and ack only after processing succeeds. Use it alongside Response Topic and Correlation Data rather than instead of it: one confirms the business outcome, the other carries the reply.
- Payload contract. Agree on a shared envelope, value, unit, quality, timestamp, before the first device connects, and enforce it centrally rather than per source system.
- OPC UA bridging. Translate the address space into your topic convention at the edge. Don't relay Part 14 PubSub as-is and call it a Unified Namespace.
Where this goes next
There's more here than one post can cover. Event-Driven Architecture deserves its own look at when choreography is the right call. The same goes for combining ISA-95 and ISA-88 inside a single namespace, and for what governance looks like once this runs across more than one site. We'll get there. For the fuller four-stage picture, connect, contextualize, analyze, act, see our companion architecture whitepaper.
The real takeaway
None of this makes OPC UA the wrong choice at the cell level, or MQTT the wrong choice for everything above it. Both protocols are doing exactly what they were designed to do. The comparisons that get this wrong usually aren't testing MQTT against OPC UA at all; they're testing a finished feature against homemade logic, or conflating hard real-time control with application-level feedback loops that MQTT 5 already handles natively.
The better question was never which protocol is faster. It's which coordination style, orchestration or choreography, fits the layer of the architecture you're actually building for.
For the architecture this piece assumes, read Connect: Building a Real-Time Data Backbone for Data Accessibility.
See how OPC UA and MQTT work together in practice in OPC UA and MQTT: How to Bridge OT Protocols for Scalable Industrial Data, or explore the technical limits of other UNS candidates in Beyond MQTT: The Fit and Limitations of Other Technologies in a UNS.
