Solving Silent Data Loss: Matching ROS 2 QoS Profiles
Stop wondering why your ROS 2 subscribers are silent. Learn how to match Reliability and Durability QoS profiles to prevent silent data loss and avoid the pitfalls of head-of-line blocking.
16 Jul 2026, 16:03 UTC

The Mystery of the Silent Subscriber
You have a publisher sending data and a subscriber listening for it. You can see the topic listed in the CLI, the nodes are active, and there are no error messages in the logs—yet the subscriber receives absolutely nothing. In ROS 2, this is rarely a networking failure and usually a Quality of Service (QoS) mismatch.
Because ROS 2 relies on DDS (Data Distribution Service) for communication, it doesn't just send packets; it negotiates a contract between the sender and receiver. If the subscriber demands a level of reliability that the publisher refuses to provide, the DDS middleware will silently drop the connection to prevent system instability. To fix this, you must align your Reliability and Durability settings based on the nature of your data.
Reliability: Guaranteed Delivery vs. Low Latency
The Reliability setting determines how the system handles packet loss. You generally choose between two profiles:
- Reliable: The publisher ensures every message reaches the subscriber. If a packet is lost, the middleware requests a retransmission. This is essential for critical commands (e.g., "Stop Robot") or state changes where missing a single update breaks the logic.
- Best Effort: The publisher sends the data and forgets it. If a packet is dropped due to network congestion, it stays dropped. This is the gold standard for high-frequency sensor data like LiDAR or IMU streams, where a new update is coming in milliseconds and an old, retransmitted packet would only cause lag.
Durability: Handling Late Joiners
While Reliability handles transmission, Durability handles persistence. By default, ROS 2 uses Volatile durability, meaning if a subscriber starts after a message was sent, it misses that message forever.
If you have a node that publishes a map or a configuration parameter once at startup, use Transient Local. This tells the publisher to save the last sent message in a local cache. When a new subscriber joins, the publisher automatically sends that cached message, ensuring the robot doesn't sit idle waiting for a heartbeat that already happened.
Implementation Example: Sensor vs. Command
Below is a conceptual configuration for a Python-based node using rclpy. Note how the sensor stream prioritizes speed, while the command stream prioritizes certainty.
import rclpy
from rclpy.qos import QoSProfile, ReliabilityPolicy, DurabilityPolicy
from std_msgs.msg import String, Float64
# 1. High-frequency sensor profile (Best Effort)
sensor_qos = QoSProfile(
reliability=ReliabilityPolicy.BEST_EFFORT,
durability=DurabilityPolicy.VOLATILE,
depth=10
)
# 2. Critical command profile (Reliable + Transient Local)
command_qos = QoSProfile(
reliability=ReliabilityPolicy.RELIABLE,
durability=DurabilityPolicy.TRANSIENT_LOCAL,
depth=1
)
# Usage in a publisher
# self.create_publisher(Float64, '/sensor_data', qos_profile=sensor_qos)
# self.create_publisher(String, '/system_config', qos_profile=command_qos)
Diagnostic Check
To verify if a mismatch is causing your data loss, run the following command in your terminal (requires ROS 2 Humble or newer):
ros2 topic info /your_topic_name --verbose
Look for the Reliability and Durability fields under both the Publisher and Subscription sections. If the Publisher is BEST_EFFORT and the Subscription is RELIABLE, the connection will fail because the subscriber's requirements are stricter than what the publisher provides.
The Trade-off: Head-of-Line Blocking
It is tempting to set everything to Reliable to avoid data loss, but this introduces a risk called Head-of-Line (HOL) blocking. In an unstable wireless network, a single lost packet in a Reliable stream forces the middleware to pause all subsequent messages while it waits for the retransmission of the missing one. This creates "bursty" data delivery and significant latency spikes, which can be catastrophic for real-time control loops.
Actionable Summary
When designing your ROS 2 communication graph, apply these rules of thumb:
- Use Best Effort for telemetry, video, and high-rate sensors.
- Use Reliable for actuators, state machines, and event triggers.
- Use Transient Local for static maps, parameters, or initial configurations.
- Always check
ros2 topic info --verbosewhen a subscriber is unexpectedly silent.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.