Embedded library guide
Use tsink as an in-process time-series engine by adding it as a Rust dependency. You get WAL durability, compaction, tiered retention, and queries — no separate process needed.Quick start
StorageBuilder
StorageBuilder configures and constructs a Storage instance.
Every setting has a sensible default; only with_data_path is required for persistent storage.
Data & persistence
| Method | Default | Description |
|---|---|---|
with_data_path(path) | none | Directory for WAL, segments, and metadata. Required for persistence. |
with_object_store_path(path) | none | Directory (or object-store prefix) for warm/cold tier segments. |
Retention
| Method | Default | Description |
|---|---|---|
with_retention(duration) | 14 days | Global retention window. Data older than this is eligible for removal. |
with_retention_enforced(bool) | false | When true, out-of-retention writes are rejected immediately. |
with_tiered_retention_policy(hot, warm) | none | Set distinct retention durations for the hot and warm tiers. |
Timestamp precision
| Method | Default | Description |
|---|---|---|
with_timestamp_precision(precision) | Nanoseconds | Interpret ingested timestamps as one of Nanoseconds, Microseconds, Milliseconds, or Seconds. |
Chunks & partitions
| Method | Default | Description |
|---|---|---|
with_chunk_points(n) | 2048 | Number of data points per in-memory chunk before sealing. |
with_partition_duration(duration) | 1 hour | Time range covered by each partition. Affects compaction and query granularity. |
with_max_active_partition_heads_per_series(n) | 8 | Maximum concurrently active partition heads per series. Controls out-of-order write fanout. |
Memory & cardinality
| Method | Default | Description |
|---|---|---|
with_memory_limit(bytes) | usize::MAX | Memory budget for in-memory data. Exceeding this triggers admission backpressure. |
with_cardinality_limit(series) | usize::MAX | Maximum number of unique series. New series are rejected once the limit is reached. |
Concurrency
| Method | Default | Description |
|---|---|---|
with_max_writers(n) | cgroup-detected CPU count | Parallel writer threads for ingestion. |
with_write_timeout(duration) | 30 s | Maximum time a write waits for a writer slot before returning WriteTimeout. |
WAL
| Method | Default | Description |
|---|---|---|
with_wal_enabled(bool) | true | Enable or disable the write-ahead log. Disabling trades durability for speed. |
with_wal_size_limit(bytes) | unlimited | Cap total WAL size on disk. Exceeding this returns WalSizeLimitExceeded. |
with_wal_buffer_size(size) | default | In-memory buffer size for WAL frame batching before flush. |
with_wal_sync_mode(mode) | PerAppend | Durability policy — see WAL sync modes. |
with_wal_replay_mode(mode) | Strict | Corruption handling during WAL replay — see WAL replay modes. |
Remote segments
| Method | Default | Description |
|---|---|---|
with_remote_segment_cache_policy(policy) | MetadataOnly | Caching strategy for remote tier segments. |
with_remote_segment_refresh_interval(duration) | default | How often to refresh the remote segment catalog. |
with_mirror_hot_segments_to_object_store(bool) | false | Copy hot-tier segments to the object store for disaster recovery. |
Runtime
| Method | Default | Description |
|---|---|---|
with_runtime_mode(mode) | ReadWrite | ReadWrite for local persistence, ComputeOnly for remote-only metadata. |
with_background_fail_fast(bool) | true | Halt the engine on unrecoverable background errors (compaction, flush). |
with_metadata_shard_count(n) | auto | Number of metadata shards for series routing. |
Writing data
Value types
tsink supports multiple value types through theValue enum:
DataPoint::new(timestamp, value) accepts anything that implements Into<Value>.
For convenience, f64 and i64 convert automatically:
Batch inserts
Pass a slice ofRow values to insert_rows:
Write acknowledgement
Useinsert_rows_with_result to inspect durability guarantees:
PerAppend— every write returnsDurable.Periodic(interval)— writes returnAppended; they become durable after the next periodic sync.- WAL disabled — writes return
Volatile.
Querying data
Simple select
Retrieve all points for a metric within a time range:Select all label combinations
Select multiple series at once
Advanced queries with QueryOptions
select_with_options provides aggregation, downsampling, and pagination:
| Aggregation | Description |
|---|---|
None | No aggregation (default) |
Sum | Sum of values |
Min / Max | Minimum / maximum |
Avg | Arithmetic mean |
First / Last | First / last point in window |
Count | Number of points |
Median | Median value |
Range | Max − Min |
Variance / StdDev | Statistical variance / standard deviation |
Paginated row scanning
For large result sets, use cursor-based scanning:Series discovery
List all known series:| Constructor | Operator | Example |
|---|---|---|
SeriesMatcher::equal(name, value) | = | method="GET" |
SeriesMatcher::not_equal(name, value) | != | status!="500" |
SeriesMatcher::regex_match(name, pattern) | =~ | host=~"web-.*" |
SeriesMatcher::regex_no_match(name, pattern) | !~ | env!~"staging|dev" |
Deleting series
Rollup policies
Define materialized downsampled views that the engine maintains automatically:Snapshots
Create an atomic, point-in-time snapshot of the entire database:Async API
AsyncStorage wraps the sync engine with a dedicated thread pool and async channels,
making it safe to use from a Tokio runtime without blocking the executor.
Wrapping an existing Storage
Async-specific options
| Option | Default | Description |
|---|---|---|
queue_capacity | 1024 | Maximum in-flight requests per internal queue. |
read_workers | cgroup CPU count | Number of dedicated reader threads. |
Arc<dyn Storage> is accessible
via inner() or recoverable with into_inner().
Custom codecs and aggregators
Store and aggregate arbitrary types by implementingCodec and Aggregator:
WAL sync modes
| Mode | Acknowledgement | Trade-off |
|---|---|---|
WalSyncMode::PerAppend (default) | Durable | Every write is fsync’d before returning. Crash-safe but higher latency. |
WalSyncMode::Periodic(interval) | Appended | Writes are buffered and fsync’d on a timer. Lower latency; a crash may lose up to one interval of writes. |
WAL replay modes
| Mode | Behaviour |
|---|---|
WalReplayMode::Strict (default) | Abort replay on any corruption. Use for production where data integrity is paramount. |
WalReplayMode::Salvage | Skip corrupted frames/segments and continue. Useful for disaster recovery when some data loss is acceptable. |
Observability
Inspect engine internals at runtime:Error handling
All fallible operations returntsink::Result<T>, which is Result<T, TsinkError>.
Key error variants to handle:
| Variant | When it occurs |
|---|---|
MemoryBudgetExceeded | Write would push memory usage past the configured limit. |
CardinalityLimitExceeded | A new series would exceed the cardinality cap. |
WalSizeLimitExceeded | WAL on-disk size exceeds the configured limit. |
WriteTimeout | No writer slot became available within write_timeout. |
InvalidTimeRange | start > end in a query. |
InvalidMetricName / InvalidLabel | Metric or label name/value violates naming rules. |
StorageClosed / StorageShuttingDown | Operation attempted after close(). |
DataCorruption | Segment or WAL integrity check failed. |
InsufficientDiskSpace | Not enough disk space for WAL or segment writes. |
OutOfRetention | Write timestamp falls outside the retention window (when enforcement is enabled). |
Labels & naming rules
- Metric names: up to 65 535 bytes, validated on write.
- Label names: up to 256 bytes.
- Label values: up to 16 384 bytes.
- Labels are automatically sorted by name to produce a canonical series identity.
Lifecycle
- Build —
StorageBuilder::new()...build()opens (or creates) the data directory, replays the WAL, and starts background threads. - Use —
insert_rows,select,select_with_options, etc. TheStoragetrait object isSend + Syncand safe to share across threads viaArc. - Close —
storage.close()flushes remaining data, syncs the WAL, and shuts down background workers. Calling any method afterclose()returnsStorageClosed.