DDS and WebRTC both move real-time data between machines, and both show up in teleoperation stacks — but asking "which one should I use" is usually the wrong question, because they were built to solve different hops of the same system. DDS is a LAN-native publish/subscribe protocol with fine-grained delivery guarantees; WebRTC is a WAN-native media and data transport built to survive NATs, firewalls, and unpredictable public internet paths. A teleoperation system that works well over real distance typically uses both.
The short version
| ROS 2 / DDS | WebRTC | |
|---|---|---|
| Designed for | Pub/sub discovery and QoS-controlled delivery on a LAN | Real-time audio/video/data over the public internet |
| Discovery | Multicast/broadcast-based automatic discovery | Signaling server + ICE candidate exchange |
| NAT traversal | None built in | ICE, with STUN for hole-punching and TURN as relay fallback |
| Encryption | Optional, via separate DDS Security spec | Mandatory — SRTP for media, DTLS for data channels |
| Congestion control | None; assumes a well-provisioned LAN | Built in (e.g. Google Congestion Control), adapts bitrate to path |
| QoS granularity | Fine per-topic: reliability, history depth, deadline, durability | Coarse: per-track bitrate/priority hints, less per-message control |
| Typical robot-side use | Internal topics: joint state, sensor data, control commands | The WAN hop to a remote operator: video, command echo |
| ROS 2 role | The middleware layer itself (via an rmw implementation) | Not a ROS 2 concept — added at the application layer for WAN links |
What DDS is actually for
DDS (Data Distribution Service) is the middleware underneath ROS 2 topics. ROS 2 talks to it through the RMW (ROS middleware) abstraction layer — you pick a concrete implementation via RMW_IMPLEMENTATION, commonly eProsima's Fast DDS (the ROS 2 default) or Eclipse Cyclone DDS (a Tier-1 alternative shipped with ROS 2 packages), with Connext and Zenoh-backed middlewares also available. Nodes discover each other automatically — no broker, no central registry — which is exactly right on a flat LAN inside a single robot or lab network.
What makes DDS distinctive is per-topic Quality of Service. Reliability chooses best-effort (send and forget, matching UDP behavior) or reliable (acknowledged, retransmitted on loss). History controls how many past samples a publisher retains for late-joining subscribers — KEEP_LAST(N) versus KEEP_ALL. Deadline and Durability add further control over timing and persistence. This granularity is the point: a 500 Hz joint-state topic and a 1 Hz battery-status topic have genuinely different requirements, and DDS lets you set them independently on the same bus.
None of this addresses the public internet. Discovery relies on multicast or broadcast traffic that most WAN paths and cloud VPCs don't route. There's no NAT traversal — DDS assumes participants can reach each other directly. There's no adaptive congestion control, because it assumes LAN-grade bandwidth and latency. And encryption is optional and separately specified (DDS Security), not on by default. Running raw DDS between a robot and a remote operator across the internet means solving all of these yourself, and you'd be re-deriving most of what WebRTC already does.
What WebRTC is actually for
WebRTC was built for browser-to-browser video calls crossing arbitrary networks, and that design shows up as exactly the capabilities DDS lacks. ICE (Interactive Connectivity Establishment) finds a viable path between two peers behind NATs, using STUN servers to discover each side's public-facing address and TURN servers to relay traffic when a direct path isn't achievable. Media is encrypted with SRTP and data channels with DTLS, both mandatory, not optional. A congestion controller continuously estimates available bandwidth and adapts encoder bitrate, which matters when the operator's connection quality changes mid-session.
The tradeoff is granularity. WebRTC gives you tracks and data channels, not per-message QoS knobs — you don't get DDS's KEEP_LAST(N) history semantics or a Deadline policy on a RTCDataChannel. It also was not built with sub-frame timing guarantees for control commands in mind; getting a teleoperation command channel to behave well under WebRTC's defaults takes deliberate tuning, covered in sub-100ms teleoperation latency — separating video and command traffic onto distinct transports or priority classes, and sizing jitter buffers for single frames rather than the multi-frame defaults browsers ship with for passive video viewing.
The architecture that actually works
The pattern that shows up across production teleoperation stacks: DDS stays on the robot's local network, carrying the topics that genuinely need LAN-grade reliability and low jitter — joint state, sensor fusion, the robot's own control loop. A bridge process sits at the edge, subscribing to the subset of DDS topics that need to reach a remote operator (video frames, teleoperation commands, status) and republishing them as WebRTC media tracks and data channel messages for the WAN hop. The operator's station reverses the process. The robot's safety-critical internal loops never touch the public internet at all; only the operator-facing slice does, over a transport built for exactly that trip.
- Communication entirely within the robot or a single LAN/site network.
- High-rate internal topics needing precise per-message reliability and history control.
- Multi-robot coordination on a shared local network with automatic discovery.
- Anywhere ROS 2's existing tooling (rqt, ros2 topic, rosbag) needs to observe traffic directly.
- The link between a robot and an operator who is not on the same network.
- Any path that crosses a NAT, firewall, or the public internet.
- Video and audio specifically — codecs, adaptive bitrate, and jitter handling are built in.
- Links where encryption must be on by default, not bolted on separately.
Latency and priority, in practice
Separation matters for one more reason: command traffic and video traffic have different tolerance for loss and different tolerance for delay. A dropped video frame is often invisible; a dropped or delayed gripper-close command is not. On the DDS side, this is why control topics are commonly configured RELIABLE with a shallow history depth while high-rate sensor topics run BEST_EFFORT — a late retransmission of a stale joint-state sample is worse than just dropping it. On the WebRTC side, the equivalent discipline is keeping command traffic off the same congestion-controlled path as video, or explicitly prioritizing it, so a bandwidth probe on the video track doesn't queue behind — or in front of — a time-critical command packet. Getting this separation right is most of what distinguishes a teleoperation link that feels responsive from one that technically works but "feels laggy," and it's the substance of the teleoperation glass-to-glass latency budget more broadly.
The recommendation
Don't pick one. Run DDS as your ROS 2 middleware for everything that stays on the robot's local network — that's what it was designed for, and its QoS system gives you control you'd otherwise have to build yourself. Run WebRTC, or a comparably built WAN transport, for the hop to a remote operator, and put a bridge process at the boundary rather than tunneling DDS traffic across the internet or trying to run robot-critical control loops over a browser media stack. Teams that try to make one protocol cover both hops end up re-implementing the other protocol's core features badly; teams that bridge them get to use each one for the job it's actually good at.