HORUS/blog

Sep 5, 2026 · dds · ros2 · middleware · networking

What Is DDS, and Why Does ROS 2 Depend On It?

DDS is the messaging standard ROS 2 was built on. What DDS does, why ROS 2 needs it, and the point where its network assumptions stop matching your robot.

DDS is the messaging standard ROS 2 was built on, and for most robots DDS beats swapping to Zenoh or a shared-memory middleware. ROS 2 depends on DDS for discovery, delivery rules and traffic between machines, which explains much of how ROS 2 behaves on a network. The verdict flips when everything runs on one board and the network was never the point, where a middleware such as HORUS fits. The rest of this post is for someone on ROS 2 who keeps meeting those three letters in error messages and wants to know what sits under their robot.

You did not go looking for DDS. You were following the ROS 2 tutorials, everything worked, and then a launch failed with a message about a participant, a domain and a delivery profile you never set. Somebody on a forum told you to export a different middleware variable, that helped once, and now there is a line in your shell profile you cannot explain to anyone.

Since then the letters keep turning up. Your robot sees all its topics on the bench and half of them in the lab. A teammate's laptop appeared in your topic list and neither of you knows why. The camera feed is fine over a cable and hesitant over Wi-Fi. The advice you keep finding is either a one-line fix with no explanation attached or a specification document written for people who already work on this layer for a living.

What you want is not a specification. You want to know what this thing is, why your robot has one at all, and whether the trouble you are having is DDS or something you did to yourself.

What is DDS, and why does ROS 2 depend on it?

DDS is a standard for programs to publish and subscribe to data across a network with no central server in the middle, and ROS 2 depends on DDS because the people who rewrote ROS chose not to build that layer themselves. The full name is Data Distribution Service, and the standard predates ROS 2 by well over a decade. DDS grew up in defence, aerospace, air traffic systems and factory automation, where machines on a shared network exchange readings continuously and nobody wants a single box whose failure silences everything.

ROS 1 had exactly that single box: a master process every node registered with. When the rewrite began, removing the master was one of the stated goals, and DDS already solved the problem in a published multi-vendor standard with implementations you could buy or download. So ROS 2 adopted DDS wholesale. Topics, services and the delivery settings you configure in a launch file are, underneath, DDS concepts wearing ROS 2 names.

That decision is why your robot discovers nodes without being told where they live. It is also why a stray laptop can join your robot's conversation uninvited.

What does a messaging layer actually do in a robot?

A messaging layer moves a piece of data from the program that produced it to the programs that need it, and that is the whole job. A camera program produces frames. A navigation program wants frames. Neither should have to know the other's address, whether the other has started yet, or what happens if the other dies halfway through the afternoon. The messaging layer answers all three questions so your code does not have to.

It does that with three pieces. Discovery is how a program announces what it publishes and finds who is listening, without a list you maintain by hand. Delivery rules are the settings that decide whether a late message is still worth sending, how many old messages to hold for a subscriber that joins late, and whether a sender should slow down for a reader that cannot keep up. Transport is the plumbing that carries the bytes, over a cable, over Wi-Fi, or between two processes on one board.

DDS supplies all three, and so does every alternative worth considering. What middleware actually does in a robot walks through the same ideas without the acronyms.

What does it look like when DDS is the thing going wrong?

It looks like a robot that behaves perfectly on your desk and falls apart the moment the network around it changes. On the bench, wired, one machine, everything appears in the topic list straight away. Take that same robot into a lab with twenty people on the wireless network and nodes start missing each other. Half your topics show up. The rest arrive much later, or only after you restart things in a particular order that nobody wrote down.

The other signature is stranger and unmistakable. A colleague opens a terminal on their own laptop, on the same network, and suddenly your robot can see their topics and they can see yours. Nothing was configured to make that happen. That is discovery doing precisely what the standard says it should, and it is a property of the network rather than a bug in your code.

Then there is the laptop that runs hot while apparently doing nothing, because it is holding a conversation with every participant it managed to find. If your trouble is instead that images arrive late over wireless, why ROS 2 struggles on ordinary Wi-Fi is the closer diagnosis.

What are the actual options for the layer underneath?

There are seven honest options, and five of them still leave you on ROS 2. The first two are the open-source DDS implementations shipped as ROS 2 defaults, Fast DDS and Cyclone DDS, which you switch between with an environment variable and no change to your code. The third is a commercial DDS product bought with support and certification evidence, which regulated industries pay for and hobby projects never need. The fourth is Zenoh through the alternative middleware layer, which keeps the ROS 2 interface while replacing the discovery and transport machinery behind most network complaints.

The fifth option leaves ROS 2 behind altogether: a middleware built for one machine rather than for a network. HORUS is that shape, an open-source real-time robotics middleware for Rust, Python and C++ where all three languages share the same shared-memory ring buffers, so messages between processes on one board are not serialised at all, offered under Apache-2.0, validated in simulation, and carrying no navigation stack of its own. The last two options are older and blunter: a broker such as MQTT for links that leave the robot, and sockets you write and maintain yourself.

How do the options compare side by side?

Read the last column first. Most people can strike four rows on sight, and the real argument is between the two that survive.

OptionWho it is forWhat it assumes you knowWhen to pick itWhen not to
Fast DDS, a ROS 2 defaultAnyone starting out on ROS 2Nothing beyond the ROS 2 tutorialsYou are learning, or working on a wired benchA busy shared wireless network is your daily reality
Cyclone DDSTeams whose discovery misbehaves on the defaultHow to set one middleware environment variableThe default has failed you and you want a cheap swapYou expect a swap alone to fix a design problem
A commercial DDSProducts facing audits and safety paperworkYour vendor's configuration model and support termsCertification evidence is a deliverableNobody is asking you for evidence
Zenoh under ROS 2Robots on Wi-Fi, or split across sitesROS 2 launch files and ordinary networkingDiscovery and wireless are your recurring painYour whole robot lives on one board
HORUSOne-board robots mixing Python, C++ and RustHow your processes split and which loop is tightSame-machine traffic is what your loop waits onYou need mapping, navigation and vendor drivers
A broker such as MQTTFleets, dashboards, and links off the robotBrokers, topics, and network failure modesData leaves the machine and deadlines are looseThe link sits inside a control loop
Sockets you write yourselfOne narrow link nobody else will touchFraming, reconnection, and your own failure modesThe system is small and will stay smallMore than one person maintains the code

Nothing in that table is a ranking. The last two columns decide it, and they decide it differently for every robot.

Do you need to understand DDS to build a robot?

No, not at the start, and most people drive a robot across a room before they ever read the three letters. The ROS 2 tutorials hide DDS deliberately, and hiding it is the right call: a publisher, a subscriber and a topic are enough mental furniture to build something that moves. You can go a long way without knowing what sits underneath, in the same way you can drive a car without knowing how a differential works.

Where that stops holding is the day something breaks in a way the tutorials do not cover. Nodes that cannot see each other. Topics that appear on one machine and not another. A robot that behaves one way in the lab and another way in the workshop. Every one of those is a discovery or delivery question, and none can be answered from inside the tidy ROS 2 abstraction. At that point you need just enough DDS to know which setting you are changing and why.

So learn it reactively. Build first, and pick up the vocabulary the week your robot starts lying to you about who it can hear.

What hardware makes DDS feel heavy?

Small single-board computers and shared wireless networks are where DDS starts to weigh on a project. Every participant keeps track of the others, holds queues for data it might need to resend, and takes part in a continuous background conversation about who exists. On a workstation none of that registers. On a low-power board already running a camera pipeline and a control loop, memory and cores are exactly what you are short of, and the background conversation competes for both.

Wireless multiplies the second half of the problem. Discovery leans on the network delivering announcements promptly to everyone who cares, and ordinary Wi-Fi handles that traffic pattern badly, especially with several machines and a crowded band. The result is a robot that behaves on a cable and turns moody without one.

None of this makes DDS the wrong choice on small hardware, and plenty of shipped robots run this way after tuning. Whether ROS 2 is too heavy for a small board goes through what actually has to be cut back to make it sit comfortably.

How long does it take to get DDS behaving on a real robot?

An afternoon on a wired bench, and an open-ended fortnight once wireless, several machines or a locked-down network are involved. The first phase is genuinely easy, and that is the trap: everything works immediately, so the messaging layer never makes it onto anyone's risk list. The second phase starts the day the robot leaves the bench, and it does not resemble the first phase at all.

What eats the time is that failures are intermittent and the feedback loop is slow. A node fails to appear now and then. You change one setting, run the system a handful of times, see nothing go wrong, and cannot tell whether you fixed the problem or got lucky. Firewalls, network interface selection, multicast being quietly dropped by a switch, and two robots sharing a domain number all produce similar symptoms with unrelated causes.

Budget for that deliberately. The teams who assume the transport is free right up until integration week are the ones who lose a month, and they lose it at the worst moment, with hardware waiting and a demo already booked.

What networking knowledge does DDS assume you already have?

DDS assumes you are comfortable with the idea that programs find each other by announcing themselves into a network, and with the vocabulary that comes attached. Multicast, unicast, network interfaces, subnets, firewall rules, and the notion that a switch or an access point may silently decline to forward something. None of that is advanced networking, and all of it is unfamiliar if your background is application code, machine learning or web work.

The second assumption is heavier. DDS exposes a wide set of delivery settings, and the defaults ROS 2 picks are a compromise rather than an answer. Knowing when to keep only the newest message rather than every message, when a subscriber should receive history it missed, and when a slow reader deserves to hold up a writer is design work that lives in your head rather than in a library you install.

If neither paragraph sounds like you today, that is not a reason to avoid ROS 2. It is a reason to keep your robot on one machine for as long as the project lets you.

What do you give up by staying on DDS?

You give up simplicity in exchange for a network you may not actually need. The configuration surface is wide, the failure modes hide in layers you did not write, and the knowledge to tune it tends to concentrate in one person, who then becomes a bottleneck every time the robot behaves oddly at a new site.

You also carry machinery you are not using. A robot whose programs all live on one board pays for discovery across a network, for delivery guarantees designed for lossy links, and for a packing and unpacking step on every message, all to talk to a program sitting a few centimetres away in the same memory. For small messages that cost is invisible and always will be. For camera frames read by three programs at once it stops being invisible, and the symptom is a control loop that misses its rhythm whenever vision gets busy.

The third thing you give up is a clear line of sight. When something arrives late, the list of places to look is long, and most of them are not your code.

When is ROS 2 the better choice?

ROS 2 is the better choice whenever the ecosystem is the point, and that covers most robots people actually build. If you want mapping, localisation, path planning, motion planning for an arm, a visualiser that shows what the robot believes about the world, recorded runs you can replay later, and a driver for the lidar you already bought, ROS 2 has all of it and HORUS has none of it. Rebuilding that catalogue is not a project, it is a career.

ROS 2 also wins on people. You can hire someone who knows it, ask a question and get an answer from somebody who hit your exact problem last year, and hand the codebase to a new engineer who used it at university. That matters more than any property of the transport underneath.

And ROS 2 wins whenever the robot is genuinely distributed: a compute board talking to a laptop, several robots coordinating, a base station in another room. Shared memory ends at the edge of one machine, so a networked robot needs a networked middleware. Whether DDS is right for your robot goes deeper on that particular call.

Is DDS the reason ROS 2 feels slow?

No, and here is why: most of the delay people blame on DDS is created above it, in code they wrote themselves. A Python callback converting an image on every frame. A planner allocating memory each cycle. A board with fewer cores than it has busy programs. A wireless link carrying more data than it can hold. Each of those produces the exact symptom people attribute to the transport, and DDS collects the blame because DDS is the only part of the system with a name you can search for.

There is a real cost down there, and it is honest to name it. Sending a message means packing the data into a flat form and unpacking a copy at the far end, and doing that for a camera frame, many times a second, separately for each subscriber, is work with nothing to show for it. That cost is worth attacking when the data is large, the rate is high, and several programs want the same item at once.

What none of it justifies is changing foundations on a hunch. Find out where the time goes before you rebuild anything.

Will switching DDS implementations fix your problems?

Partly, but not the way you think: swapping implementations changes which set of problems you have rather than removing the category. Fast DDS and Cyclone DDS make different choices about discovery traffic, memory footprint and defaults, so a team drowning in discovery on a crowded network often does get relief from a swap, and the swap costs an environment variable rather than a rewrite. That is a genuine and cheap thing to try early.

What a swap cannot do is change the shape of your system. If a camera stream is larger than the wireless link you are pushing it through, every implementation fails the same way. If four programs on one board each want their own copy of every frame, the copying is inherent to sending messages between processes and not a property of any vendor. If your own callback is the slow part, nothing underneath it will save you.

So try the swap, because it is quick and occasionally decisive. Just do not let a quick fix stand in for the measurement that tells you what to change next.

How do you decide which DDS problem you actually have?

Answer three questions in order and the diagnosis usually falls out on its own. First: does your robot span more than one machine? If everything runs on one board, every network property of DDS is overhead rather than a feature, and the interesting question becomes what your programs pass to each other and how large it is. If the robot really is distributed, you need a networked middleware, and the question becomes which one.

Second: is the network yours? A dedicated wired link between two boards behaves nothing like a shared office network with other people's machines on it. Most of the horror stories come from the second situation, and a good share of them are cured by isolating the network rather than replacing anything.

Third: is your data large and read repeatedly? Joint angles and velocity commands cost nothing to copy. Camera frames read by three programs on one board are a different animal, and that is the one case where the messaging layer itself is worth changing.

Answer those, and you know whether you have a configuration problem, a network problem, or a foundation problem.

Here is the whole decision in five lines.

The HORUS Fit Framework compresses this onto five axes you can score any option against: ecosystem size, setup effort, team size fit, deployment target, and licence. For this decision, deployment target does most of the work, because a one-board robot and a robot spread across a building have genuinely different right answers.

When your robot does grow into a same-machine traffic problem, the useful thing is having the option already on your shelf rather than starting a search under deadline. Put HORUS on that shelf now: star it so it is in your list when you start building.

Found this useful? Share it:Discuss on HNShare on X