Skip to main content

Durability QoS Policy

The Durability policy controls whether samples are available to late-joining readers.

Values

ValueDescriptionPersistence
volatile()Samples only for connected readersNone
transient_local()Writer caches samples for late joinersIn-memory
persistent()Samples persisted to diskDisk

Volatile (Default)

Samples are only delivered to readers that are connected when the sample is written.

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("streaming_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let writer = participant
.topic::<VideoFrame>("video/stream")?
.writer()
.qos(QoS::best_effort().volatile())
.build()?;

Use cases:

  • Real-time sensor data
  • Video/audio streaming
  • Data where history doesn't matter

Transient Local

Writers cache samples in memory. Late-joining readers receive cached samples.

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("config_publisher")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let writer = participant
.topic::<Configuration>("system/config")?
.writer()
.qos(QoS::reliable().keep_last(100).transient_local())
.build()?;

// Write some samples
writer.write(&config1)?;
writer.write(&config2)?;

// Later, a new reader joins and receives config1, config2

Characteristics:

  • Samples persist as long as writer exists
  • Cache size controlled by History policy
  • Memory usage = history depth × sample size
  • Lost when writer terminates

Use cases:

  • Configuration/state topics
  • Last-known-good values
  • Initialization data

Persistent

Samples are persisted to disk. Survives application restarts.

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("event_logger")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Persistent event log survives restarts
let writer = participant
.topic::<AuditEvent>("audit/events")?
.writer()
.qos(QoS::reliable().keep_all().persistent())
.build()?;

Characteristics:

  • Samples survive writer/application restart
  • Higher write latency (disk I/O)
  • Disk usage = configured limits

Use cases:

  • Event logs
  • Audit trails
  • Mission-critical state

Compatibility Rules

Durability has an ordered compatibility: writer must offer at least what reader requests.

WriterReaderMatch?
persistent()persistent()✅ Yes
persistent()transient_local()✅ Yes
persistent()volatile()✅ Yes
transient_local()transient_local()✅ Yes
transient_local()volatile()✅ Yes
transient_local()persistent()❌ No
volatile()volatile()✅ Yes
volatile()transient_local()❌ No
volatile()persistent()❌ No

Rule: Writer.durability >= Reader.durability

Late Joiner Behavior

Memory Considerations

Transient Local Memory Usage

Memory = history_depth × avg_sample_size × max_instances

Example:

  • History depth: 100
  • Sample size: 1 KB
  • Instances: 10
  • Memory: 1 MB

Examples

Configuration Topic

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("config_server")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Writer publishes configuration, late joiners get latest
let writer = participant
.topic::<AppConfig>("system/config")?
.writer()
.qos(QoS::reliable().keep_last(1).transient_local())
.build()?;

// Reader expects to receive current config on join
let reader = participant
.topic::<AppConfig>("system/config")?
.reader()
.qos(QoS::reliable().transient_local())
.build()?;

Event Log

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("audit_logger")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Persistent event log survives restarts
let writer = participant
.topic::<AuditEvent>("audit/events")?
.writer()
.qos(QoS::reliable().keep_all().persistent())
.build()?;

Volatile Streaming

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("video_streamer")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Real-time video stream, no caching needed
let writer = participant
.topic::<VideoFrame>("video/stream")?
.writer()
.qos(QoS::best_effort().keep_last(1).volatile())
.build()?;

Interaction with History

Durability and History work together:

DurabilityHistoryCached Samples
volatile()Any0 (no cache)
transient_local()keep_last(N)Last N samples
transient_local()keep_all()All samples (bounded by ResourceLimits)
persistent()keep_last(N)Last N per instance on disk
persistent()keep_all()All samples on disk

Next Steps