Skip to main content

Quality of Service Overview

Quality of Service (QoS) policies control how DDS delivers data, providing fine-grained control over reliability, timing, resource usage, and more.

Why QoS?

Different applications have different requirements:

Use CaseRequirements
Sensor streamingHigh rate, some loss OK
CommandsGuaranteed delivery, ordered
State syncLate joiners get current state
Real-time controlLow latency, deadline monitoring

QoS policies let you configure these behaviors declaratively.

QoS Policy Categories

┌─────────────────────────────────────────────────────────────┐
│ QoS Policy Groups │
├─────────────────┬─────────────────┬─────────────────────────┤
│ Data Delivery │ Timing │ Resource Management │
│ - Reliability │ - Deadline │ - History │
│ - Durability │ - Latency Budget│ - ResourceLimits │
│ - History │ - Lifespan │ │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Ownership │ Ordering │ Lifecycle │
│ - Ownership │ - DestinationOrd│ - Liveliness │
│ - OwnershipStr │ - Presentation │ - WriterDataLifecycle │
│ │ │ - ReaderDataLifecycle │
├─────────────────┴─────────────────┴─────────────────────────┤
│ Metadata: UserData, TopicData, GroupData, Partition │
└─────────────────────────────────────────────────────────────┘

Core QoS Policies

Reliability

Controls whether data delivery is guaranteed:

// Best effort - may lose samples (default)
let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort);

// Reliable - guaranteed delivery with retransmits
let qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
});

Durability

Controls data persistence for late-joining subscribers:

// Volatile - no history for late joiners (default)
let qos = DataWriterQos::default()
.durability(Durability::Volatile);

// Transient Local - keep samples in memory
let qos = DataWriterQos::default()
.durability(Durability::TransientLocal);

// Persistent - survive process restart
let qos = DataWriterQos::default()
.durability(Durability::Persistent);

History

Controls how many samples are kept:

// Keep last N samples per instance (default: 100)
let qos = DataWriterQos::default()
.history(History::KeepLast { depth: 10 });

// Keep all samples
let qos = DataWriterQos::default()
.history(History::KeepAll);

QoS Compatibility

Writers and readers must have compatible QoS to communicate:

Writer QoS          Reader QoS           Match?
──────────────────────────────────────────────────
Reliable --> Reliable Yes
Reliable --> BestEffort Yes
BestEffort --> BestEffort Yes
BestEffort --> Reliable NO

Persistent --> Persistent Yes
Persistent --> TransientLocal Yes
Persistent --> Volatile Yes
TransientLocal--> TransientLocal Yes
TransientLocal--> Volatile Yes
TransientLocal--> Persistent NO
Volatile --> Volatile Yes
Volatile --> TransientLocal NO

Rule: Writer must offer at least what Reader requests.

Applying QoS

At Creation Time

// Topic QoS (defaults for endpoints)
let topic_qos = TopicQos::default()
.reliability(Reliability::Reliable { max_blocking_time: Duration::from_secs(1) });

let topic = participant.create_topic_with_qos::<Data>("Topic", topic_qos)?;

// Writer QoS
let writer_qos = DataWriterQos::default()
.history(History::KeepLast { depth: 100 });

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

// Reader QoS
let reader_qos = DataReaderQos::default()
.history(History::KeepLast { depth: 50 });

let reader = subscriber.create_reader_with_qos(&topic, reader_qos)?;

QoS Inheritance

TopicQos

├──> DataWriterQos (inherits, can override)

└──> DataReaderQos (inherits, can override)

PublisherQos

└──> DataWriterQos (partition, presentation)

SubscriberQos

└──> DataReaderQos (partition, presentation)

Common QoS Profiles

Sensor Streaming

let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort)
.durability(Durability::Volatile)
.history(History::KeepLast { depth: 1 });

State Synchronization

let qos = DataWriterQos::default()
.reliability(Reliability::Reliable { max_blocking_time: Duration::from_secs(1) })
.durability(Durability::TransientLocal)
.history(History::KeepLast { depth: 1 });

Command Queue

let qos = DataWriterQos::default()
.reliability(Reliability::Reliable { max_blocking_time: Duration::from_secs(30) })
.durability(Durability::Volatile)
.history(History::KeepAll);

Event Log

let qos = DataWriterQos::default()
.reliability(Reliability::Reliable { max_blocking_time: Duration::from_secs(5) })
.durability(Durability::Persistent)
.history(History::KeepAll);

Timing Policies

Deadline

Monitor data freshness:

let qos = DataWriterQos::default()
.deadline(Deadline::new(Duration::from_millis(100)));

// Writer must publish within 100ms, or deadline missed callback fires

Liveliness

Detect writer failures:

let qos = DataWriterQos::default()
.liveliness(Liveliness::Automatic {
lease_duration: Duration::from_secs(10),
});

// Writer automatically asserts liveliness
// Reader notified if writer stops for 10s

Lifespan

Auto-expire old samples:

let qos = DataWriterQos::default()
.lifespan(Lifespan::new(Duration::from_secs(60)));

// Samples older than 60s are automatically discarded

Resource Management

Resource Limits

let qos = DataReaderQos::default()
.resource_limits(ResourceLimits {
max_samples: 10000, // Total samples
max_instances: 100, // Unique keys
max_samples_per_instance: 100, // Per key
});

Time-Based Filter

let qos = DataReaderQos::default()
.time_based_filter(TimeBasedFilter::new(Duration::from_millis(100)));

// Receive at most one sample per 100ms

Metadata Policies

User Data

// Attach metadata to participant
let config = DomainParticipantConfig::default()
.user_data(b"app=sensor;version=2.1".to_vec());

Partition

// Filter communication
let pub_qos = PublisherQos::default()
.partition(Partition::new(vec!["sensors", "zone_a"]));

let sub_qos = SubscriberQos::default()
.partition(Partition::new(vec!["sensors", "zone_*"]));

QoS Policy Summary

PolicyApplies ToPurpose
ReliabilityTopic, W, RDelivery guarantee
DurabilityTopic, W, RHistorical data
HistoryTopic, W, RSample buffer
DeadlineTopic, W, RUpdate rate
LivelinessTopic, W, RFailure detection
LifespanTopic, WSample expiration
ResourceLimitsTopic, W, RMemory bounds
OwnershipTopic, W, RExclusive writers
OwnershipStrengthWWriter priority
DestinationOrderTopic, RSample ordering
PresentationPub, SubAccess scope
PartitionPub, SubTopic filtering
TimeBasedFilterRRate limiting
UserDataParticipantMetadata
TopicDataTopicMetadata
GroupDataPub, SubMetadata

Troubleshooting QoS

No Match (QoS Incompatible)

Warning: Writer and Reader QoS incompatible

Check:

  • Reliability: Writer ≥ Reader
  • Durability: Writer ≥ Reader
  • Deadline: Writer ≤ Reader
  • Liveliness: Writer kind ≥ Reader kind

Missed Deadlines

Warning: Deadline missed

Solutions:

  • Increase deadline period
  • Reduce publish rate
  • Check for network issues

Resource Exhaustion

Error: ResourceLimitExceeded

Solutions:

  • Increase max_samples
  • Use KeepLast instead of KeepAll
  • Consume samples faster

Next Steps