A lightweight time-series database written in Rust. Embed it, run it as a server, or scale it as a cluster.
Rust
324
155 commits
updated Aug 6, 2026
A lightweight time-series database written in Rust.
Embed it, run it as a server, or scale it as a cluster.
protoc is vendored at build time.Add tsink as a dependency and get a full time-series engine in-process — WAL durability, compaction, retention, and queries included.
use tsink::{DataPoint, Row, StorageBuilder, TimestampPrecision};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let storage = StorageBuilder::new()
.with_data_path("./tsink-data")
.with_timestamp_precision(TimestampPrecision::Milliseconds)
.build()?;
storage.insert_rows(&[
Row::new("cpu_usage", DataPoint::new(1_700_000_000_000_i64, 42.0)),
])?;
let points = storage.select("cpu_usage", &[], 1_700_000_000_000, 1_700_000_000_001)?;
println!("{points:?}");
storage.close()?;
Ok(())
}
UniFFI bindings expose the core API as a native Python module:
from tsink import TsinkStorageBuilder, DataPoint, Row, Value
builder = TsinkStorageBuilder()
builder.with_data_path("./tsink-data")
db = builder.build()
db.insert_rows([
Row(
metric="cpu_usage",
labels=[],
data_point=DataPoint(timestamp=1_700_000_000_000, value=Value.F64(v=42.0)),
)
])
print(db.select("cpu_usage", [], 0, 2_000_000_000_000))
A single binary that speaks every major metrics protocol.
cargo run -p tsink-server --bin tsink-server --release -- \
--listen 127.0.0.1:9201 \
--data-path ./var/tsink
Write data with any client you already have:
# Prometheus text exposition
curl -X POST http://127.0.0.1:9201/api/v1/import/prometheus \
-H 'Content-Type: text/plain' \
-d 'http_requests_total{method="GET"} 1027 1700000000000'
# PromQL query
curl 'http://127.0.0.1:9201/api/v1/query?query=http_requests_total'
Enable clustering with a flag and scale horizontally. tsink handles shard routing, replication, consistency, hinted handoff, repair, and rebalance automatically.
tsink-server \
--listen 0.0.0.0:9201 \
--data-path ./var/tsink \
--cluster-enabled \
--cluster-node-id node-1 \
--cluster-bind 0.0.0.0:9211 \
--cluster-replication-factor 3 \
--cluster-seeds node-2:9212,node-3:9213
| Capability | Details |
|---|---|
| Durability | Segmented WAL with configurable sync — per-append (crash-safe) or periodic (throughput-optimized). Strict or salvage replay on recovery. |
| Compaction | LSM-style leveled compaction (L0 → L1 → L2) with tombstone-aware merging and atomic segment replacement. |
| Tiered storage | Automatic hot → warm → cold lifecycle with configurable retention windows. Object-store backing for warm/cold tiers. |
| Encoding | Adaptive timestamp codecs (fixed-step, delta-varint, delta-of-delta), Gorilla XOR float compression, and zstd for persisted segments. |
| Data types | float64, bytes, and native Prometheus histograms. |
| Memory control | Configurable memory budget with admission-based backpressure. Cardinality limits on unique series. |
| Reads | mmap-based zero-copy segment reads. Downsampling, aggregation, and regex-capable label matchers built in. |
| Protocol | Endpoint | Notes |
|---|---|---|
| Prometheus Remote Write | POST /api/v1/write | Snappy-framed protobuf |
| Prometheus Remote Read | POST /api/v1/read | |
| Prometheus Text Exposition | POST /api/v1/import/prometheus | Bulk import |
| InfluxDB Line Protocol | POST /write, POST /api/v2/write | v1 and v2 compatible |
| OTLP HTTP | POST /v1/metrics | Protobuf; gauges, sums, histograms, summaries |
| StatsD | UDP (--statsd-listen) | Counter, gauge, timer, set |
| Graphite | TCP (--graphite-listen) | Plaintext protocol |
/healthz and /ready — Kubernetes-compatible probes/metrics — Prometheus-format self-instrumentationStorageBuilder configuration, sync and async APIs, snapshotsTsinkStorageBuilder, type mappings, error handling/metrics endpoint, self-instrumentation, health probes, support bundlesMIT — see LICENSE.
155 commits
Rust
99.4%
A lightweight time-series database written in Rust. Embed it, run it as a server, or scale it as a cluster.
Rust
324
155 commits
updated Aug 6, 2026
A lightweight time-series database written in Rust.
Embed it, run it as a server, or scale it as a cluster.
protoc is vendored at build time.Add tsink as a dependency and get a full time-series engine in-process — WAL durability, compaction, retention, and queries included.
use tsink::{DataPoint, Row, StorageBuilder, TimestampPrecision};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let storage = StorageBuilder::new()
.with_data_path("./tsink-data")
.with_timestamp_precision(TimestampPrecision::Milliseconds)
.build()?;
storage.insert_rows(&[
Row::new("cpu_usage", DataPoint::new(1_700_000_000_000_i64, 42.0)),
])?;
let points = storage.select("cpu_usage", &[], 1_700_000_000_000, 1_700_000_000_001)?;
println!("{points:?}");
storage.close()?;
Ok(())
}
UniFFI bindings expose the core API as a native Python module:
from tsink import TsinkStorageBuilder, DataPoint, Row, Value
builder = TsinkStorageBuilder()
builder.with_data_path("./tsink-data")
db = builder.build()
db.insert_rows([
Row(
metric="cpu_usage",
labels=[],
data_point=DataPoint(timestamp=1_700_000_000_000, value=Value.F64(v=42.0)),
)
])
print(db.select("cpu_usage", [], 0, 2_000_000_000_000))
A single binary that speaks every major metrics protocol.
cargo run -p tsink-server --bin tsink-server --release -- \
--listen 127.0.0.1:9201 \
--data-path ./var/tsink
Write data with any client you already have:
# Prometheus text exposition
curl -X POST http://127.0.0.1:9201/api/v1/import/prometheus \
-H 'Content-Type: text/plain' \
-d 'http_requests_total{method="GET"} 1027 1700000000000'
# PromQL query
curl 'http://127.0.0.1:9201/api/v1/query?query=http_requests_total'
Enable clustering with a flag and scale horizontally. tsink handles shard routing, replication, consistency, hinted handoff, repair, and rebalance automatically.
tsink-server \
--listen 0.0.0.0:9201 \
--data-path ./var/tsink \
--cluster-enabled \
--cluster-node-id node-1 \
--cluster-bind 0.0.0.0:9211 \
--cluster-replication-factor 3 \
--cluster-seeds node-2:9212,node-3:9213
| Capability | Details |
|---|---|
| Durability | Segmented WAL with configurable sync — per-append (crash-safe) or periodic (throughput-optimized). Strict or salvage replay on recovery. |
| Compaction | LSM-style leveled compaction (L0 → L1 → L2) with tombstone-aware merging and atomic segment replacement. |
| Tiered storage | Automatic hot → warm → cold lifecycle with configurable retention windows. Object-store backing for warm/cold tiers. |
| Encoding | Adaptive timestamp codecs (fixed-step, delta-varint, delta-of-delta), Gorilla XOR float compression, and zstd for persisted segments. |
| Data types | float64, bytes, and native Prometheus histograms. |
| Memory control | Configurable memory budget with admission-based backpressure. Cardinality limits on unique series. |
| Reads | mmap-based zero-copy segment reads. Downsampling, aggregation, and regex-capable label matchers built in. |
| Protocol | Endpoint | Notes |
|---|---|---|
| Prometheus Remote Write | POST /api/v1/write | Snappy-framed protobuf |
| Prometheus Remote Read | POST /api/v1/read | |
| Prometheus Text Exposition | POST /api/v1/import/prometheus | Bulk import |
| InfluxDB Line Protocol | POST /write, POST /api/v2/write | v1 and v2 compatible |
| OTLP HTTP | POST /v1/metrics | Protobuf; gauges, sums, histograms, summaries |
| StatsD | UDP (--statsd-listen) | Counter, gauge, timer, set |
| Graphite | TCP (--graphite-listen) | Plaintext protocol |
/healthz and /ready — Kubernetes-compatible probes/metrics — Prometheus-format self-instrumentationStorageBuilder configuration, sync and async APIs, snapshotsTsinkStorageBuilder, type mappings, error handling/metrics endpoint, self-instrumentation, health probes, support bundlesMIT — see LICENSE.
155 commits
Rust
99.4%