Sep 5, 2026 · ros2 · mqtt · middleware · robot-networking
ROS 2 vs MQTT: Which Belongs in Your Robot?
ROS 2 belongs inside the robot and MQTT belongs between the robot and the outside world, and here is how to tell which of those jobs you actually have.
ROS 2 belongs inside the robot and MQTT belongs between the robot and everything outside it, and most working machines use both. ROS 2 moves sensor streams between programs that must agree on timing; MQTT moves small status messages over an unreliable link. The verdict flips when your device has no real control loop, where MQTT alone suffices and HORUS or ROS 2 is overhead. The rest of this post is for anyone wiring a robot to a dashboard, a fleet server or a phone app and unsure which layer does which job.
You already know MQTT from something that was not a robot. A home sensor, a factory line, a batch of devices reporting temperatures to a server that drew you a graph. It was small, it was explainable to a colleague in a minute, and it kept working when the Wi-Fi hiccuped. Now you are building a robot, somebody has handed you a framework with a build system and a package layout and a week of tutorials, and the obvious question arrives: why not use the thing you already understand? A broker is running anyway for the dashboard. The camera publishes, the planner subscribes, and the whole vocabulary transfers. Meanwhile the counterargument is being made loudly in another tab by someone insisting you will regret it, without saying which day the regret arrives or what it looks like when it does. Underneath all of it sits a question with a clean answer that nobody states plainly: are these two things competing for the same job, or are they doing different jobs that happen to use the same word for a topic?
Should I use ROS 2 or MQTT inside my robot?
Use ROS 2 inside the robot and MQTT for everything that leaves it, because the two are solving different problems that happen to share a vocabulary. Inside a machine, several programs need the same picture of the world at roughly the same moment: the camera frame, the wheel odometry, the arm's joint angles, the map. They run on hardware you own, across a link you control, and they fail together or not at all. Outside the machine, one robot reports to something far away over a connection that will drop in a lift, in a tunnel, or when a site engineer reboots a switch nobody told you about. Those two sets of constraints pull in opposite directions. A layer built for the second job puts a broker in the middle, which is exactly what you want when the link is unpredictable and exactly what you do not want when a planner needs the newest frame. The exception is a device that is not really a robot, where inside and outside are the same short conversation.
What do ROS 2 and MQTT each actually do?
ROS 2 is a robotics framework and MQTT is a message protocol with a broker in the middle, and that difference settles most of the argument. MQTT does one small thing well: a client connects to a broker, publishes messages under a topic string, subscribes to topic patterns, and the broker fans each message out to whoever is listening. MQTT adds delivery settings you choose per message, a last-will message for when a client vanishes, and retained messages so a new subscriber immediately learns the current state. ROS 2 gives you that same publish-and-subscribe idea plus a catalogue: drivers for real sensors, bookkeeping that tracks where the gripper sits relative to the base, a clock every program agrees on, a recorder that replays a whole run at your desk, a viewer that draws what the robot believed it saw, and navigation that crosses a building without hitting furniture. One is plumbing. The other is plumbing plus the robot parts you were hoping not to write. If that split is new, what middleware actually does in a robot fills it in.
What are the real options for moving messages around a robot?
There are six realistic layers, and a shipped robot usually runs two or three of them at once. ROS 2 handles the inside of the machine, where programs share sensor data and need one clock. MQTT handles the trip from the machine to a fleet server, a dashboard or a phone, over a link nobody promises will stay up. A bridge process sits between the two, deciding what leaves the robot and in what shape, which is nearly always far less than everything. For the innermost loop, where sensing and control share one computer and a late message becomes a stutter you can see, a shared-memory middleware such as HORUS keeps Rust, Python and C++ processes reading and writing the same ring buffers instead of serialising to each other, and pairs with ROS 2 rather than displacing it. Underneath all of that, plain firmware on a microcontroller drives motors over a cable and answers to none of these layers. And a vendor fleet platform can take over the outward half entirely, if you are content to live inside somebody's console.
Which layer fits which job?
Match each layer to a job rather than picking a winner, because the winner question has no answer and the job question has an obvious one. Before reading the rows, write down two sentences: what has to happen inside the robot within one control cycle, and what somebody far away needs to see or send. The first sentence points at one column of this table and the second points at another, and very few projects find both sentences answered by the same row.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| ROS 2 inside the robot | Machines whose programs share sensor data | Linux, a build tool, package management | Planners, drivers and controllers need one picture | The device is two sensors reporting to a server |
| MQTT out to the world | Fleets, dashboards, phone apps | A broker, topics, retained messages | The link is remote and expected to drop | Anything on a deadline inside the machine |
| A bridge between the two | Teams shipping robots to customers | Both layers, and what to filter out | You want remote status without exposing the graph | One robot on a bench you can plug into |
| HORUS on the robot's own computer | Builders mixing Rust, Python and C++ | Those languages, and life outside the ROS package set | Sensing and control share a computer and cannot be late | You need drivers, planning or fleet messaging |
| Plain web requests to a server | Devices that report occasionally | Web basics and a server you run | Updates are rare and started by the device | The server has to push commands promptly |
| A vendor fleet platform | Buyers of a finished platform | The vendor's console and pricing | You want dashboards without building them | You need to own the data path |
| Firmware talking over a serial cable | Single-board machines | C, timers, interrupts | The whole robot is one loop with one cable out | Cameras, maps or several programs at once |
Am I a robotics team or an IoT team?
Your background predicts which mistake you are about to make, so it is worth naming honestly. Someone arriving from connected devices sees a robot as a device with more sensors, reaches for the broker they already run, and discovers three months later that nothing agrees on what time it is and every program invented its own message shape. Someone arriving from robotics sees the outside world as another topic, publishes the whole graph to the network, and discovers that a link outside their control does not behave like a bench cable. Both mistakes are recoverable and both cost a quarter. The useful move is to notice which half of the system you find boring, because that is the half you will underestimate. If dashboards and fleets bore you, take a platform for the outward half. If drivers and coordinate frames bore you, take the framework rather than writing them badly. Teams of one or two should be ruthless here: the half you find boring is the half you should buy, borrow or bridge rather than build.
What hardware am I putting this on?
Hardware decides how much of this argument even applies to you. A robot with a single small board carrying camera, planner and controller has an inside problem and barely an outside one, and adding a broker to that board means messages leave a program, cross into another process, and come back, for no reason other than familiarity. A robot with a perception computer and a separate motor board has an inside problem that crosses a cable, which is where a framework earns its place. A fleet of machines scattered across a site or a city has an outside problem that dominates everything, and the broker is the right answer for the part that crosses the site. A microcontroller with two motors and a temperature sensor has no inside problem at all, and both of these layers are more than the machine needs. Draw your robot as boxes and lines, then mark every line that leaves the chassis. The lines that stay inside and the lines that leave want different tools.
How soon does this have to work?
Timeline decides how much of the split you build now and how much you leave a door open for. With a demo four weeks out, use whatever your team already knows and put one thin seam where the robot talks to the outside world, so the outward half can change later without touching the inward half. That seam costs an afternoon and saves a rewrite. With a year and a product at the end of it, build the split properly from the start: the framework inside, the broker outward, a bridge process that names exactly which topics leave and in what shape. The expensive mistake is not choosing wrong on day one; it is letting the two halves grow into each other, so that every program on the robot talks directly to a broker and nothing can be tested without one running. Teams that hit that wall usually meet it the week a customer asks for an offline mode, and untangling it takes longer than building the seam would have.
What do I need to know before either one makes sense?
MQTT is learnable in an afternoon and ROS 2 is not, and that gap is the reason this question gets asked at all. MQTT needs you to understand a broker, topic strings, delivery settings, retained messages and a last will, and a competent developer has all five by the end of the day. ROS 2 asks for Linux, a build tool, a package layout, a launch system, a message description language and a mental model of coordinate frames, which is a genuine month. That asymmetry makes MQTT feel like the sensible choice and it is a trap, because the afternoon buys you plumbing and the month buys you plumbing plus drivers, recording, replay and a viewer. Judge the cost against what you would otherwise write yourself. If your robot needs none of the catalogue, the afternoon really is enough. If it needs three catalogue items, the month is the cheaper purchase, and the honest complaint list about the framework tells you which parts of that month hurt.
What do I give up if I build the whole robot on MQTT?
You give up agreement, and agreement is most of what a robot framework sells. On a broker-only robot, nothing enforces a shared message shape, so the vision program emits one kind of payload and the planner parses a slightly different one, and the day they drift you get a bug that only shows up on hardware. Nothing supplies a shared clock, so the timestamp on a camera frame and the timestamp on a wheel reading are two opinions rather than one fact. Nothing tracks where the gripper sits relative to the base, so the transform mathematics becomes your code, forever. There is no recorder that captures a run and replays it at your desk, so debugging goes back to printing. And no vendor driver speaks to a broker, so every sensor gets a wrapper you wrote. That is a real amount of work, and none of it is the interesting part of your robot. Why projects outgrow their first framework is largely a description of this bill arriving.
When is ROS 2 the better choice?
ROS 2 is the better choice for anything with several programs that share sensor data, which is nearly every machine anyone calls a robot. Take ROS 2 when a planner needs the camera frame and the odometry to describe the same instant, when you want mapping or arm planning without writing them, when a driver for your sensor already exists, when a simulator is in your loop, and when you would rather debug from a recorded run than from print statements. HORUS is not the answer in those cases either: a shared-memory middleware on one computer ships no drivers, plans no paths and carries nothing across a site. Take ROS 2 also when you plan to hire, because the tutorials, the courses and the forum answers all assume it, and a candidate who has debugged a transform tree at midnight is worth finding. MQTT is the better choice only for the part of the system where the network is the hard problem, and that part is real but small.
Can MQTT replace ROS 2 entirely?
No, and here is why. Replacing the framework with a broker replaces one component and leaves the other nine unfilled, because publish-and-subscribe was never the expensive part. What you actually need from a robot framework is a shared clock, a common message shape everyone compiles against, coordinate bookkeeping, sensor drivers, a recorder, a replayer, a viewer, a launch system that starts eleven programs in the right order, and a simulator that speaks the same language as the hardware. A broker supplies none of them, so a serious broker-only robot ends up with a home-made version of each, written under deadline and understood by one person. The teams who genuinely do run broker-only machines are almost always running something that is not a robot in the demanding sense: a conveyor, a sensor mast, a cabinet of instruments. The tell is whether anything on the machine has to close a loop before a person could react. If nothing does, the broker is enough and the framework is overhead.
Is MQTT too slow for a robot?
Partly, but not the way you think. The problem is not that a broker moves messages badly, because a local broker on a quiet network moves small messages perfectly well and plenty of machines run happily that way. The problem is shape. Every message takes an extra hop through a separate process, a large camera frame gets encoded into a payload and decoded again at the other end, and when the connection stalls the client retries in the background while your controller waits for something that already stopped being useful. On a good day none of that is visible. On a bad day the arm keeps moving on last cycle's information, and the failure appears as a stutter or an overshoot rather than an error anyone can point to. That is why the honest rule is about position rather than speed: a broker is right where you expect an unreliable link and wrong where a message has to arrive before the next control cycle needs it. What a control loop is and why its timing matters is the background for that rule.
What does a robot running both actually look like?
A robot running both has a wall down the middle, with the framework on one side and the broker on the other, and one small program acting as the door. Inside the wall, the camera driver publishes frames, the perception program consumes them, the planner produces a path, and the controller drives the wheels, all agreeing on a clock and on message shapes. At the wall stands a bridge process with an explicit list: battery level, current mission, pose, a health summary, a handful of error codes going out, and mission assignments, stop requests and configuration coming in. Outside the wall lives the broker, the fleet server, the dashboard the operations team stares at, and the phone app somebody demanded. The bridge is deliberately narrow, and narrowness is the whole point. When the network dies, the robot keeps working and the bridge queues; when the dashboard team wants a new field, they ask for one line in the bridge rather than a change inside the robot. Machines built this way survive both a bad network and a new dashboard.
How do I decide between them this week?
Decide by writing the two sentences and then running one cheap test. The first sentence names what has to happen inside the robot before the next control cycle, in plain words: the arm stops before it hits the table, or the wheels stop before the robot reaches the edge of the dock. The second sentence names what somebody far away needs to see or send, also in plain words: where the robot is, whether the battery is low, and how to tell it to go home. If the first sentence is empty, you do not have a robot problem and a broker is enough on its own. If the second sentence is empty, you do not need a broker yet and adding one now is early. If both have content, you are building both halves and the only real decision left is where the wall goes. Then test it: unplug the network mid-run and see what the robot does. That single experiment tells you more than a fortnight of reading comparisons.
Take the line that matches you:
- If you are wiring a robot to a dashboard -> both, with a narrow bridge, because the halves solve different problems.
- If your device is a few sensors reporting to a server -> MQTT alone, because there is no loop to protect.
- If several programs on the machine share a camera stream -> ROS 2 inside, because they need one clock and one message shape.
- If sensing and control share one computer and cannot be late -> a shared-memory layer under the framework, because the broker hop is the part that hurts.
- If you already run a fleet platform -> its own agent for the outward half, because you will not out-build their dashboards.
The HORUS Fit Framework is the checklist behind those lines, and not one of its five axes is a number: ecosystem size, setup effort, team size fit, deployment target, and licence. Score each layer you are weighing on all five, and the axis you cannot compromise on ends the argument.
Brokers and frameworks stopped competing once you see the wall between them. If the inside half is where your trouble lives, and Rust, Python and C++ on one computer could read the same ring buffers with nothing serialised between them, HORUS is open source under Apache-2.0. Star it so it is in your list when you start building.