Skip to main content

Reliability QoS Policy

The Reliability policy controls whether data delivery is guaranteed or best-effort.

Values

ValueDescriptionUse Case
BestEffortFire and forget, no retransmissionSensor data, video streaming
ReliableGuaranteed delivery with ACK/NACKCommands, state synchronization

Best Effort

Samples are sent once without acknowledgment. If a sample is lost due to network issues, it is not retransmitted.

use hdds::prelude::*;

let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort);

let writer = publisher.create_writer_with_qos(&topic, qos)?;

Characteristics:

  • Lowest latency (no ACK overhead)
  • No blocking on write
  • Samples may be lost
  • No memory accumulation for retransmission

Reliable

Samples are acknowledged by readers. Lost samples trigger NACK-based retransmission.

use hdds::prelude::*;
use std::time::Duration;

let qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
});

let writer = publisher.create_writer_with_qos(&topic, qos)?;

Parameters:

  • max_blocking_time: Maximum time write() can block waiting for buffer space

Characteristics:

  • Guaranteed delivery (if reader is reachable)
  • Higher latency due to ACK/NACK protocol
  • Writer may block if reader is slow
  • Memory used for retransmission buffer

Protocol Details

RTPS Reliable Protocol

Heartbeat Mechanism

Writers periodically send HEARTBEAT messages announcing available sequence numbers. Readers respond with ACKNACK indicating which samples they need.

ParameterDefaultDescription
Heartbeat period100 msTime between heartbeats
NACK response delay10 msDelay before sending NACK
Max retransmissionsUnlimitedRetries until timeout

Compatibility Rules

Writers and readers must have compatible reliability settings:

WriterReaderMatch?
RELIABLERELIABLE✅ Yes
RELIABLEBEST_EFFORT✅ Yes
BEST_EFFORTBEST_EFFORT✅ Yes
BEST_EFFORTRELIABLENo Match
Incompatibility

A BEST_EFFORT writer cannot satisfy a RELIABLE reader. The reader expects acknowledgments that the writer won't send.

Performance Considerations

Best Effort

// High-frequency sensor data (1000+ Hz)
let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 1 });
  • Latency: ~100 μs
  • Throughput: Up to 4M msg/s
  • Memory: Minimal (no retransmission buffer)

Reliable

// Critical commands requiring guaranteed delivery
let qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_millis(100),
})
.history(History::KeepLast { depth: 100 });
  • Latency: ~500 μs - 10 ms (depends on network)
  • Throughput: Up to 100K msg/s
  • Memory: History depth × sample size

Blocking Behavior

With Reliable, the write() call may block:

// Non-blocking write with timeout
match writer.write(&sample) {
Ok(()) => println!("Sample sent"),
Err(Error::Timeout) => println!("Buffer full, sample dropped"),
Err(e) => return Err(e),
}

To avoid blocking:

  1. Increase max_blocking_time for bursty traffic
  2. Use larger history depth to buffer samples
  3. Ensure readers keep up with writer rate

Examples

Telemetry (Best Effort)

// High-rate sensor data where occasional loss is acceptable
let writer_qos = DataWriterQos::default()
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 1 });

let reader_qos = DataReaderQos::default()
.reliability(Reliability::BestEffort);

Commands (Reliable)

// Robot commands that must not be lost
let writer_qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(5),
})
.history(History::KeepAll);

let reader_qos = DataReaderQos::default()
.reliability(Reliability::Reliable);

Mixed System

// Writer offers reliable (stronger guarantee)
let writer_qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
});

// Reader A accepts best-effort (compatible)
let reader_a_qos = DataReaderQos::default()
.reliability(Reliability::BestEffort);

// Reader B requires reliable (compatible)
let reader_b_qos = DataReaderQos::default()
.reliability(Reliability::Reliable);

Next Steps