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.
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
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
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.
| Entry | What it provides |
|---|---|
$system/replications/<robot-name>/robot-to-central | Replication status and errors, pending and failed record counts, transferred data size, and execution duration |
$system/lifecycle/<robot-name>/compress-robot-data | Compression-policy status and errors, processed records and blocks, progress, and execution duration |
$system/usage/<robot-name>/total | Instance-wide storage, record, and read/write traffic statistics |
$system/usage/<robot-name>/robot-data | The same usage statistics for the local robot-data bucket |
$system/logs/<robot-name>/messages | Captured 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.