Skip to main content
Version: Next

Buffering, replication, and monitoring

This guide explains how to configure a robot-side ReductStore instance to keep a bounded local history, replicate selected ROS topics to a shared destination bucket, compress older local data, and record operational diagnostics. It uses Docker Compose and startup provisioning, but the same ReductStore settings apply when another application writes the records instead of ReductBridge.

The complete example stores ROS records in a local robot-data bucket, replicates camera and IMU entries to the public Play server under a robot-specific prefix, and writes replication, lifecycle, usage, and log events to the $system bucket.

Data flow

ReductBridge continues writing to local storage when the network is unavailable. When connectivity returns, the replication task resumes sending queued camera and IMU records. A lifecycle policy compresses older local blocks, while system events expose the state of each background operation.

Play serverbucket: demo<robot-name>/*$system bucketreplication + lifecycle diagnostics | usage | warnings and errorsReductBridgerobot-datareplication taskROS records20 GB FIFO buffercamera + IMU onlyHTTPScompression policyzstd after one day

Deployment

ReductStore is available as a Docker image, a Snap package, and prebuilt binaries for Linux, macOS, and Windows. See the Getting Started guide for all installation options.

The ROS example uses the following reductstore service from the example docker-compose.yml:

reductstore:
image: reduct/store:latest
restart: unless-stopped
ports:
- "127.0.0.1:8383:8383"
environment:
RS_API_TOKEN: my-token
# Keep diagnostic entry paths stable across container recreation.
RS_INSTANCE_NAME: ${ROBOT_NAME:-robot-1}

# bucket-buffering-start
# Keep the newest 20 GB of robot data on local disk.
RS_BUCKET_1_NAME: robot-data
RS_BUCKET_1_QUOTA_TYPE: FIFO
RS_BUCKET_1_QUOTA_SIZE: 20GB
# bucket-buffering-end

# replication-start
# Send selected topics to the public demo instance.
RS_REPLICATION_1_NAME: robot-to-central
RS_REPLICATION_1_SRC_BUCKET: robot-data
RS_REPLICATION_1_DST_BUCKET: demo
RS_REPLICATION_1_DST_HOST: https://play.reduct.store
RS_REPLICATION_1_DST_TOKEN: reductstore
RS_REPLICATION_1_DST_PREFIX: ${ROBOT_NAME:-robot-1}
RS_REPLICATION_1_ENTRIES: "/camera/image_raw,/imu/data"
# replication-end

# compression-start
# Compress local data after one day.
RS_LIFECYCLE_1_NAME: compress-robot-data
RS_LIFECYCLE_1_TYPE: compress
RS_LIFECYCLE_1_BUCKET: robot-data
RS_LIFECYCLE_1_OLDER_THAN: 1d
RS_LIFECYCLE_1_INTERVAL: 1h
# compression-end
volumes:
- reduct-data:/data

The service publishes the ReductStore HTTP API on 127.0.0.1:8383 and mounts the reduct-data volume at /data. Binding the port to the loopback interface keeps the example API off external network interfaces. The volume preserves records, bucket settings, replication progress, lifecycle state, and system events across container restarts. The local API token is my-token; ReductBridge or any other writer must use this token when connecting to the local instance.

RS_INSTANCE_NAME uses the ROBOT_NAME environment variable to keep system event paths stable when Docker Compose recreates the container. The same value is used as the destination prefix, separating records from different robots. If ROBOT_NAME is unset, both settings default to robot-1.

The service is part of the complete Docker Compose example. The complete ROS pipeline requires Docker with Docker Compose and host networking. On Docker Desktop, enable host networking before starting the containers. See Docker's host networking documentation for platform requirements and configuration.

Clone the documentation repository and enter the example directory:

git clone https://github.com/reductstore/website.git
cd website/docs/ros/example

Choose a unique robot name and start ReductBridge. Docker Compose also starts its ReductStore and ROS publisher dependencies, but not the unrelated Grafana and query services:

export ROBOT_NAME="robot-1"
docker compose up -d reduct-bridge
Public demo server

The example replicates data to the demo bucket on the public Play server using its reductstore demo token. Do not send sensitive data to this shared server.

For production, replace the destination URL, bucket, and token with values for your own ReductStore instance. Also replace the local my-token value in both docker-compose.yml and bridge.toml. The destination token must have permission to write to the target bucket. Keep the local API bound to a trusted interface or protect it with a firewall, and use HTTPS for communication outside a trusted network.

Configuration

info

You can create and manage ReductStore resources through the HTTP API, SDKs, CLI, or Web Console. For robot deployments, provisioning resources with environment variables is often more convenient because the same configuration can be applied consistently across an entire fleet. This example uses environment-variable provisioning.

ReductStore reads provisioning variables when the container starts. At startup, ReductStore creates the robot-data bucket, the robot-to-central replication task, and the compress-robot-data lifecycle policy. Provisioned resources cannot be removed through the API while their environment variables remain configured.

Local buffer

The following bucket settings create a bounded local buffer:

# Keep the newest 20 GB of robot data on local disk.
RS_BUCKET_1_NAME: robot-data
RS_BUCKET_1_QUOTA_TYPE: FIFO
RS_BUCKET_1_QUOTA_SIZE: 20GB

The robot-data bucket uses a 20 GB FIFO quota, so the robot can continue recording without unbounded disk growth. When the bucket reaches its quota, ReductStore removes its oldest data to make room for new records. ReductStore guarantees that stored data does not exceed the quota: if old data cannot be removed or there is still insufficient space, it rejects new records instead of exceeding the limit.

ReductBridge can request the same bucket settings when it connects, but bucket creation is not required in this deployment because the ReductStore service already provisions robot-data at startup.

Selective replication

The replication settings connect the local bucket to the public demo instance, limit transfers to the camera and IMU entries, and identify the source robot:

# Send selected topics to the public demo instance.
RS_REPLICATION_1_NAME: robot-to-central
RS_REPLICATION_1_SRC_BUCKET: robot-data
RS_REPLICATION_1_DST_BUCKET: demo
RS_REPLICATION_1_DST_HOST: https://play.reduct.store
RS_REPLICATION_1_DST_TOKEN: reductstore
RS_REPLICATION_1_DST_PREFIX: ${ROBOT_NAME:-robot-1}
RS_REPLICATION_1_ENTRIES: "/camera/image_raw,/imu/data"

The robot-to-central task watches new records in robot-data and sends /camera/image_raw and /imu/data to the demo bucket. With ROBOT_NAME=robot-1, the destination prefix stores them as robot-1/camera/image_raw and robot-1/imu/data. Assign each robot a unique name, such as robot-1, robot-2, and so on, so an entire fleet can replicate into one bucket without entry-name collisions. This is especially important on the shared Play server.

ReductStore batches transfers and tracks pending records in a transaction log. A network interruption does not stop local ingestion, and replication resumes when the destination becomes available. Replication starts with records written after the task is created; it does not automatically backfill older records or replicate deletions.

The FIFO quota and replication log are separate limits. Size both for the longest expected network outage and data rate to avoid dropping pending records from the log or evicting local data before it has been replicated.

Compression

The lifecycle settings reduce the size of older data while it remains in the local buffer:

# Compress local data after one day.
RS_LIFECYCLE_1_NAME: compress-robot-data
RS_LIFECYCLE_1_TYPE: compress
RS_LIFECYCLE_1_BUCKET: robot-data
RS_LIFECYCLE_1_OLDER_THAN: 1d
RS_LIFECYCLE_1_INTERVAL: 1h

The compress-robot-data policy runs once per hour and compresses persisted blocks older than one day with zstd. Compression does not delete records, and reads automatically decompress the data, so clients do not need to handle compression. The FIFO quota remains the final storage bound.

See ReductStore provisioning for startup environment variables, replication settings for transaction-log limits and TLS options, data replication for entry and label filters, and lifecycle policies for compression and retention options.

Monitoring

ReductStore records operational events as time-indexed records in the $system bucket. These events let you monitor replication and lifecycle execution, track storage and traffic usage, and investigate warnings or errors without adding a separate logging pipeline.

In the paths below, <robot-name> is the ROBOT_NAME value supplied when the stack starts. Configuring this stable instance name keeps diagnostics grouped under the same entries after container recreation.

EntryWhat it provides
$system/replications/<robot-name>/robot-to-centralReplication status and errors, pending and failed record counts, transferred data size, and execution duration
$system/lifecycle/<robot-name>/compress-robot-dataCompression-policy status and errors, processed records and blocks, progress, and execution duration
$system/usage/<robot-name>/totalInstance-wide storage, record, and read/write traffic statistics
$system/usage/<robot-name>/robot-dataThe same usage statistics for the local robot-data bucket
$system/logs/<robot-name>/messagesCaptured ReductStore warnings and errors

System events are enabled by default and can be queried like other records with the HTTP API, SDKs, CLI, or Web Console. See replication diagnostics, lifecycle diagnostics, and system event settings for event fields, retention, and log-level configuration.