Technical whitepaper · v1.12

The VeltrixDB whitepaper.

How the storage engine actually works — the read and write paths, the durability argument and its limits, the sharding and replication model, the search subsystem, and how the engine handles failure. Written for the engineer who'll be on call for this in production.

Author · Akanksha Gupta Updated · Oct 2026 License · Apache 2.0 (open source) · benchmark conditions stated
VeltrixDB · technical reference
covers v1.12 · versions marked
shareable
PDF on request

The extreme point-lookup engine — architecture & durability.

A first-principles walk through the storage layer, the I/O model, the sharding scheme, and exactly when an acknowledged write is durable on commodity NVMe — and when it is not.

v1.12
covers
8192
index shards
2.0
Apache license
Why we wrote it

Open source, documented to the last byte.

VeltrixDB is open source under Apache 2.0 — every line is on GitHub. But reading the Go source isn't how most teams evaluate a database, so we also wrote this architectural document. It's the fastest way for a CTO or security-review team to understand exactly how the engine works — and the source is right there when they want to go deeper.

01 Storage engine

Key–value separation, end to end.

How VeltrixDB separates keys from values — the 64 B index entry (~142 B/key of RAM in practice, plus ~90 B/key for the ordered index), the VLog record format (4 KB-aligned, magic + CRC32C), block packing (~26 × 128 B records per 4 KB block, on the MultiPut and GC paths only — a single Put takes a whole block), and why write amplification is ~1× by design (not measured) when there is no LSM compaction.

Chapter 1–2
02 Kernel I/O

pread, pwrite and fdatasync — and where io_uring fits.

Reads are one Go pread per cache miss; a write batch is one pwrite and one fdatasync. Why the io_uring write bridge is opt-in (off by default), and what it measured on a 4-CPU CI runner.

Chapter 3
03 Durability

The fsync chain, crash replay and checkpoints.

Adaptive group commit (default since v1.12: a lone writer is synced at once; 15 ms is only the upper bound), why VLog and WAL fdatasync run concurrently, full replay after a crash, the compacted checkpoint written on clean shutdown, Raft vs replicated mode (one or the other, never both), and the conditions under which an acknowledged write can be lost.

Chapter 4
04 Sharding & placement

8192 index shards · consistent hashing · rack-aware.

One FNV-1a hash drives three placements: 8192 index shards, up to 256 cache shards, and the disk. Across nodes, a consistent-hash ring (64 virtual nodes each) that the client routes on — the server does not forward — over static --peers membership, and --rack-id placement that keeps copies of a partition in different racks or zones.

Chapter 5
05 Cache (LIRS)

Why LRU lies — and what we replaced it with.

The LIRS algorithm in detail, value-aware eviction (values ≤ 256 B get priority 2 and are kept longer; a 16-entry window from the cold end evicts the largest, lowest-priority value first), and why the cache is split into up to 256 shards (one lock was 21.7% of CPU; a hit went from 711 ns to ~92 ns).

Chapter 6
06 Failure modes

How the engine handles failure.

Crash restart, silent disk corruption, a slow disk, GC falling behind, node loss. For each: what the engine does, which metric shows it, and what is tested today (end-to-end failover, persistence and backup/restore suites).

Chapter 7–8
07 Search subsystem

Vector, full-text and hybrid search on the same records.

HNSW vector indexes (float32, int8 or product-quantized; layer-0 graph on the heap or in a mapped file), a BM25 inverted index, and reciprocal-rank fusion of the two — all derived from ordinary durable keys and filtered by the KV record with the same id. Shipped in v1.11 and v1.12.

Chapter 10
08 Data model

More than GET and PUT — and what it still is not.

TTLs, INCR / CAS / SETNX, hashes with per-field TTL, lists, sets, namespaces, ordered RANGE / SCANCUR, secondary indexes, and one-shot TXN (per-key version check, read-committed, not MVCC). No sorted sets, pub/sub, streams, Lua or RESP.

Chapter 11 · appendix
A sneak peek

The kind of detail you need before you commit.

Two pulled-out figures from the document — the write path, and the failure matrix.

Figure 03 · Write path

Adaptive group commit with amortized fsync.

A PUT is compressed, then encrypted (if enabled), then appended to the VLog and the WAL concurrently. The caller waits for max(WAL, VLog), not their sum. Concurrent writers share a single write(2) and a single fdatasync; only then is the index entry installed, the cache updated and the write acknowledged. Since v1.12 group commit is adaptive by default: a lone writer is synced at once, concurrent writers after an idle gap of about one fdatasync, and the 15 ms window is only the upper bound (--group-commit=fixed restores the full wait). With an emulated 300 µs fdatasync on macOS, a lone writer's P50 went from 16 ms to 0.45 ms and 64 writers from 4.0K to 37.5K writes/s.

The chapter covers the binary WAL record (48-byte header, CRC32C over the whole record; the default since v1.6, with --wal-format=text as rollback), crash replay, the compacted checkpoint written on clean shutdown, and the exact conditions under which an acknowledged write survives a single-node crash.

FIG 03 · WRITE PATH · SINGLE PUTACK after fdatasync
01 · route
FNV-1a→shard / disk
02 · transform
compress→encrypt
03 · in parallel
VLog append·WAL adaptive group-commit
04 · index
install entry·version++
05 · ack
cache insert→OK
Figure 14 · Failure matrix

Every failure mode we handle, and the signal it raises.

The failure chapter maps each failure to what the engine does about it and the Prometheus metric that shows it happening. It also says what is tested today — the end-to-end suites cover node failover, persistence across restarts and backup/restore — and what is not.

The point of publishing this isn't to say nothing ever fails — it's to say which failures we know about, and how you'll see them. We don't publish recovery-time numbers we haven't measured reproducibly.

FIG 14 · FAILURE MATRIXsignal, not SLA
crash
kill -9→WAL replay
bit rot
CRC32C scrub→scrub_corruption_total
slow disk
latency EWMA→vlog_disk_slow
GC behind
65% garbage→emergency GC
node loss
FAILED after 10 s→raft re-election
Table of contents

Every chapter, in order.

Every section, every figure number, every page. If a chapter is what you're after, we'll send you the chapter — you don't have to take the whole PDF.

VeltrixDB · Technical Reference · v1.12

12 sections · versions marked
00Preface & notationAudience, scope, and how to read this paperp. 1
01The case for key-value separationWhy LSM compaction is the silent tail-latency killerp. 4
02Storage engine internalsVLog record format, per-shard index (Go map, or off-heap native table since v1.6), garbage collectionp. 9
03Kernel I/O — pread, pwrite, fdatasyncThe Go read path, one pwrite per batch, the opt-in io_uring write bridgep. 16
04Durability & its limitsAdaptive group commit (v1.12), binary WAL format (v1.6), crash replay, checkpoints, Raft vs replicated modep. 22
05Sharding & placement8192 index shards, client-side consistent-hash routing, static --peers membership, rack-aware placement, rebalancingp. 26
06LIRS cache & small-hot-key resistanceThe eviction algorithm, the priority-2 tuning, large cold values evicted firstp. 31
07Failure modesFailure matrix, the metric each one raises, what is tested today, runbooksp. 34
08Security modelTLS / mTLS, AES-256-GCM at rest, auth, plaintext PITR archivesp. 38
09Engine work — 2026 (v1.6–v1.12)Native index, binary WAL, ordered-index fix, experimental C++ front-end, adaptive group commit, Raft read barrier, what is not wired inp. 39
10Search subsystemHNSW (float32 / int8 / PQ, disk graph), BM25, hybrid RRF, filters, cluster fan-out, rebuild on startnew · v1.11+
11Appendix — data model, wire protocol & metrics referenceCommands and data types, binary protocol spec, Prometheus metrics referencep. 45
Chapter 7 · sample

Six failure modes and how you'll see them.

A taste of the failure chapter — what the engine does in each case and the Prometheus metric that shows it. Where something is covered by the end-to-end test suites, we say so; we don't quote recovery times we haven't measured reproducibly.

01

Crash restart

A crash (or kill -9) means a full replay of wal.log on start. Writes are acknowledged only after WAL and VLog fdatasync, so on Linux an acknowledged write is on disk (macOS fsync returns at the drive cache: crash-safe, not power-loss-safe). A clean shutdown instead writes a compacted checkpoint (one record per live key) and renames it over the WAL. Covered by the persistence e2e suite.

02

Keys the old WAL could not replay

The legacy text WAL truncated replay for keys containing | or a newline, so acknowledged writes could be lost on a crash restart. The binary WAL (default since v1.6) fixes this and reads old text records mixed in.

03

Silent disk corruption

Every VLog record carries a magic number and a CRC32C, checked on every read. A background scrubber walks the log; any mismatch increments veltrixdb_scrub_corruption_total. Any non-zero rate means investigate.

04

A slow or failing disk

Per-disk read and write latency EWMAs are sampled continuously. A disk at ≥ 5× the median raises veltrixdb_vlog_disk_slow. Each disk has its own WAL and VLog, so a failure on one disk does not touch the others.

05

GC falling behind

GC pauses under read pressure, which alone could stall it forever. It escalates in three tiers and at 65% garbage bypasses the pause unconditionally; a pause left over from a write-only period also clears once no read has arrived for 4 minutes. Each bypass increments veltrixdb_vlog_gc_emergency_runs_total; a persistent rate means writes exceed sustainable GC bandwidth.

06

Node loss

A node is FAILED after 10 s without a heartbeat and is left out of search fan-out, but it stays on the hash ring, so the client keeps routing its keys to it. In --mode=raft a lost leader is replaced by election (400–800 ms timeout) and writes follow MOVED. In --mode=replicated on v1.13 and earlier a replica whose send fails is marked FAILED and is not brought back until the primary restarts. Fixed in v1.14: failed replicas are re-probed with backoff and caught up (SYNC_PENDING → SYNC), and a RECOVERING node returns to ACTIVE after 2 good pings. On v1.14 and earlier a node marked FAILED also starts auto-rebalance, which deletes keys outside the Raft log: killing the leader of a loaded 3-node raft cluster left the survivors with 5,435 and 7,875 of 20,000 keys. Run with --auto-rebalance=false until you upgrade. Fixed in v1.15: node failures never migrate keys, raft mode never migrates, and replicated mode deletes a key only after every replica acknowledged it. Nothing re-creates lost copies. Covered by the node-failover e2e suite; we don't publish recovery times we haven't measured reproducibly.

Chapter 9 · sample

Engine work, v1.6–v1.12.

Chapter 9 documents the engine changes that shipped from v1.6 to v1.12. Every number states its conditions, including the ones that did not go our way.

01

Off-heap native index

Each shard’s index moves into a C++ table off the Go heap on cgo builds (macOS included). Go’s GC no longer scans it. Measured at 5M keys: full GC 21 → 0.27 ms, settled RSS 168 → 142 B/key, for ~19 ns more per cache-miss lookup. Needs vm.max_map_count ≥ 262144 at large key counts.

02

Binary WAL

48-byte little-endian header, CRC32C over the whole record. Fixes lost writes on crash replay for keys with | or a newline. Encoding 4× faster per record, replay 2.5× faster. --wal-format=text writes the legacy format as a rollback.

03

Ordered-index overwrite fix

Overwriting a live key no longer re-inserts it into the RANGE skiplist. Server batch writes (8 clients × 1024-key MPUT, 1M keys, macOS): 1.45M → 3.54M keys/s, P99 9.6 → 4.2 ms.

04

C++ network front-end — experimental

--net=cpp: an event loop per core, binary protocol only, standalone mode only, opt-in. On a 4-CPU CI runner: read P50 154 vs 286 µs, but read P99 ~3.0 vs 1.8 ms and batch writes ~12% lower. Not faster overall. Disk-bound reads now finish off the loop (deferred reads); not re-measured yet.

05

io_uring write bridge — now opt-in

It used to start on every Linux cgo build. A VLog batch is already one pwrite + one fdatasync, and with the C++ storage extras all on the CI runner measured 1.12M vs 1.77M keys/s batch writes. Per-part attribution is pending; scripts/net-bench.sh bisects it. VELTRIXDB_URING_BRIDGE defaults to off.

06

Adaptive group commit — v1.12

The WAL and VLog flushers share one pacer. A lone writer is synced at once; concurrent writers after an idle gap of about one fdatasync (EWMA, clamped 20 µs–2 ms); the 15 ms window is only the upper bound. Emulated 300 µs sync, macOS: lone-writer P50 16 → 0.45 ms; 64 writers 4.0K → 37.5K writes/s at the same writes per fdatasync. Durability is unchanged.

07

Raft read barrier — v1.12

A freshly elected leader used to serve a local GET before applying everything its predecessor had acknowledged. Reads now wait (≤ 2 s) for the leader’s no-op to apply. Without it a unit test missed the acknowledged write in 20 of 20 failovers; with it, 0 of 20. In v1.12 it covers GET and MGET only: hash, namespace and RANGE / SCANCUR reads stay local. Fixed in v1.14: every read on both protocols passes it (namespace, hash, list, set, range, VER, IDXQUERY, QUERY and searches).

08

Soak and crash tests — v1.12

Nightly: a 20-minute search soak checked against an oracle of acknowledged writes, and 10 SIGKILL / restart cycles. In 3 local cycles every acknowledged vector, document and record was present after restart and no acknowledged delete came back. Writes in flight at the kill are not checked.

—

What is not wired in

cpp/ also holds an ART index, a priority io_uring scheduler, an SQPOLL reader, a C++ VLog and an eBPF GC throttle. They compile, and nothing in Go calls them. The read path is Go pread. The chapter says so explicitly rather than listing them as features.

Get the full whitepaper in your inbox.

One email gets you the PDF — including the chapter you skipped. If you want a specific chapter, mention it in the body and we'll send just that.

Apache 2.0 open source · architecture documented in full · read the code on GitHub