VeltrixDB Docs
v1.1.0 GitHub FAQ Quickstart

Performance Tuning

VeltrixDB's throughput and latency are governed by a small number of knobs: the WAL/VLog flush window, cache size, batching, and admission control. This page summarizes the tuning guidance from the project's performance guide.

The most important knob: flush windows

Both the WAL and VLog use group-commit: writes arriving within a configurable window share a single fdatasync. Keep -wal-flush-window-ms and -vlog-flush-window-ms equal at all times.

writes/s ~ goroutines x (1000 / window_ms)
GoalWindowP99 write
Lowest latency (low concurrency)0 ms~0.2 ms
Low latency2 ms~2.2 ms
100K+ writes/s5 ms~5.2 ms
Default (balance)10 ms~10.2 ms
Maximum throughput20 ms~20.2 ms
./veltrixdb --wal-flush-window-ms 5 --vlog-flush-window-ms 5

Widening the window trades write latency (one window's worth, at most) for higher sustained write throughput by amortizing fdatasync across more writers per batch.

Batch operations

Always prefer MultiPut/MultiGet over individual PUT/GET calls when operating on multiple keys — they share a single network round trip.

MethodThroughputWhen to use
Individual PUT~10K/s per goroutine at a 10 ms windowSingle key
MultiPut, 1024 keys~108K/s (macOS) / ~426K/s (Linux)Any multi-key write

The TCP server automatically coalesces back-to-back PUTs from the same connection into a MultiPut, so batching benefits apply even without client-side changes.

Disk density and packing

Batched writes pack multiple records per 4 KB VLog block, which materially changes on-disk density at small value sizes:

Avg valueDisk per record (packed)Gain vs. legacy 4 KB
64 B88 B47x
128 B152 B27x
256 B280 B15x
512 B536 B7.6x
4 KB+4096 B1x

Packing is automatic for MultiPut and pipelined PUTs. A single unbatched Put uses the unpacked lock-free path instead. You can verify actual packing efficiency with veltrixdb_vlog_file_bytes / veltrixdb_storage_writes_total ~ value_size + 24.

Cache tuning

-cache 65536      # 64 GB
--auto-tune       # VeltrixDB picks 85% of available RAM
--read-heavy      # 400 GB preset + scan-resistant tuning

-read-heavy is a preset documented in the server flags reference as a 400 GB cache with an extended GC interval — use it for workloads dominated by reads where you can afford more RAM and want to bias GC toward less frequent, larger passes.

Check cache effectiveness with veltrixdb_cache_hits_total / (hits + misses). Small values (≤256 B) resist eviction more aggressively under the LIRS policy, so workloads with many small values benefit the most from a larger cache.

Admission control

VeltrixDB throttles background GC based on an exponentially-weighted moving average (EWMA) of read latency, to keep GC from competing with foreground reads for NVMe bandwidth:

Read EWMAWhat happens
< 2 msFull speed
< 3 msNormal
≥ 3 msGC capped at 60 MB/s
≥ 4 msGC paused, and each PUT sleeps 2 ms
No reads for 4+ minutesEWMA considered stale — GC auto-resumes

If veltrixdb_storage_write_admission_throttles_total is rising, read latency has crossed the 4 ms threshold and writes are being intentionally slowed to protect read latency. Diagnose the underlying cause with veltrixdb_storage_read_latency_seconds before changing any other knob — raising the cache size or flush window will not help if the disk itself is the bottleneck.

Common problems

SymptomCheckFix
Write P99 highveltrixdb_storage_write_admission_throttles_total risingRead latency too high — see admission control above
Cache hit rate lowvlog_gc_skipped_empty_total risingIncrease -cache or enable KV separation
GC not runningvlog_gc_skipped_paused_total risingWait up to 4 minutes for the stale EWMA to clear
reads_total = 0 with live trafficBinary versionUpdate — a fixed release restores the missing metrics call
False failure-detector alerts (single node)fd.SetLocalNode not calledCall it before fd.Start() in your cluster setup