PRODUCT

What it is, how it works, and what it will not do.

The engine, the read/write path, the built-in vector and hybrid search, where it fits - and the honest list of requirements before you commit.

Sound familiar

Every fast-growing team hits the same wall.

Your database was fine at 1M users. Somewhere between 10M and 100M, things got expensive. Then slow. Then both.

Our database bill tripled and we didn't ship a single feature.

More data means more reads. More reads mean bigger Redis clusters or paying DynamoDB per million ops. The bill grows faster than revenue.

— Illustrative scenario
Latency is fine at 9 AM, then spikes at noon.

Traditional databases run internal cleanup jobs that fight your user requests for disk access. Peak traffic + compaction = your worst nightmare.

— Illustrative scenario
We're burning through SSDs every few months.

Databases without key-value separation rewrite your data over and over. Every unnecessary rewrite is wear on expensive NVMe — a tax on your latency.

— Illustrative scenario
Compared

Why replace what you're running today.

A feature-by-feature look at how VeltrixDB stacks up against the databases teams typically outgrow.

Capability Redis DynamoDB Cassandra ★VeltrixDB
Where the values live All in DRAM Managed, AWS-priced SSD, LSM tree NVMe values · DRAM index
Predictable infra cost RAM-bound Pay per million ops Ops overhead Fixed infrastructure
Compaction-free reads No compaction Managed, opaque LSM compaction No LSM · GC off the read path
Cloud portability Self-managed work AWS-only Yes Helm · any cloud
Observability included Roll your own CloudWatch only Roll your own 70+ metric families + Grafana
Vector / hybrid search Redis Query Engine (Redis Stack / Redis 8) Via a separate service (e.g. OpenSearch) Vector search in 5.0 (SAI) HNSW + BM25 + RRF, in the server
Redis protocol (RESP) Native No No (CQL) No · own text / binary protocol
Time to production Days Minutes Weeks One helm install

Competitor cells describe what their vendors publish; we have not tested them, and no same-hardware benchmark against Redis, DynamoDB, Cassandra or any vector database has been run. The comparison harness is bench/compare in the main repo.

Architecture

Fast, simple, and it just works.

All the complexity is hidden. You write data. You read data. Here is exactly what happens in between — the step labels are the mechanism, not timings.

› Data path · 8192 index shards Read packet Write packet
AppWALVLogIndexCache
Single-key write · 128 B value · TCP binary protocol
PATH 01 / 03 — DURABLE WRITE

Value lands on NVMe before ack.

The value is appended to the VLog and its pointer to the WAL at the same time; the two fdatasyncs race, so you wait for the slower one, not the sum. The group-commit WAL shares one write(2) and one fdatasync across every writer in the batch. Group commit is adaptive by default (since v1.12): a lone writer is synced at once, and the 15 ms window is only an upper bound. Records are binary with a CRC32C over the whole record.

01Hash key → 1 of 8192 shardsFNV-1a
02VLog append (O_DIRECT)atomic offset
03WAL record, in parallelbinary · CRC32C
04Both fdatasync'd → index entry64 B
05Cache insert → ackdurable
Group commit · adaptive, window upper bound ≤ 15 ms
Under the hood

Not a wrapper. A storage engine, rebuilt.

We didn't put a faster cache in front of a slow database. We built the storage layer around one bet — separate keys from values — and then took the index off the garbage collector's plate.

Technical whitepaper · 42 pages

Want the full architectural document?

Block-by-block diagrams of the write/read paths, the durability and crash-recovery model, the sharding model, the LIRS cache internals, and the chaos-engineering failure matrix — in one document. Written for the engineer who'll be on call for this in production.

9 chapters 18 diagrams v0.9.5 · June 2026
01
Storage engine

Key–value separation, WiscKey-style.

LSM trees rewrite values over and over as compaction merges levels — typically a 10–30× write amplification tax on NVMe endurance and tail latency. We split keys from values.

Each of the 8192 index shards holds a 64-byte record per key — disk offset, size, TTL, version. Values live in an append-only VLog on NVMe, one per disk, written once; there is no LSM compaction. Value-log GC runs in the background, copies only still-live values out of mostly-dead segments, and throttles itself when read latency rises — it is off the read path.

That makes write amplification close to 1× by design — the only rewrite is GC relocating live data. We have not published a write-amplification measurement; the performance page lists what we have measured and under which conditions.

Write amp
~1×
by design, not measured
Index record
64 B
per key, in DRAM
Index shards
8192
FNV-1a routed
Inspired by the WiscKey paper (FAST '16) — production-hardened for sharded multi-cloud deployments.
See the benchmark Cost impact
02
Memory & I/O · native index since v1.6

An index the garbage collector never scans.

A Go map holding hundreds of millions of index entries is something the GC has to walk. Since v1.6 the index lives off the Go heap entirely.

Since v1.6: on cgo builds (Linux and macOS, and the Docker image) each shard's index is a C++ table — 64-byte records, 8-byte tag/position slots, a per-shard key arena, large arrays individually mmap'd. Measured with 5M keys: full GC 21 ms → 0.27 ms, settled RSS 168 → 142 B/key, for ~19 ns more per cache-miss lookup. VELTRIXDB_INDEX=map opts out; CGO_ENABLED=0 builds keep the Go map. Hosts need vm.max_map_count ≥ 262144 at large key counts.

The rest of the hot path is deliberately plain. Reads are a Go pread, 4 KB-aligned, checked against magic + CRC32C. VLog batches are one contiguous pwrite and one fdatasync; the WAL flusher does one write(2) per group-commit batch. An io_uring bridge for VLog batch writes exists but is opt-in and off by default (VELTRIXDB_URING_BRIDGE): with a batch already down to one pwrite, it saves at most one syscall. The full picture is in the technical whitepaper.

Full GC · 5M keys
0.27 ms
was 21 ms · v1.6
Cache hit
~92 ns
in-process, sharded LIRS
VLog batch
1
pwrite + fdatasync
Open source under Apache 2.0. Every component is on GitHub and the architecture is documented in full — read the code, or the whitepaper.
Get the whitepaper Measured numbers
03
Engine work · v1.6–v1.12

What shipped, and what didn't pay off.

v1.6 through v1.12 carry engine changes we measured — including one that did not pay off overall. v1.13 (2026-10-01) was documentation and test fixes over v1.12; v1.14 (2026-10-05) and v1.15 (2026-10-07) fix correctness gaps and make Raft persistence incremental; v1.16 (2026-10-08, the latest release) adds mutex / block profiling flags and striped read counters.

Binary WAL (default since v1.6). 48-byte header, CRC32C over the whole record. Keys containing | or a newline no longer cut replay short — with the old text format, an acknowledged write after such a key could be lost on a crash restart. Encoding is 4× faster per record, replay 2.5× faster; old text WALs still replay. Ordered index: overwrites of a live key no longer re-insert into the skiplist — server batch writes went from 1.45M to 3.54M keys/s (8 clients × 1024-key MPUT, 1M keys, macOS).

Adaptive group commit (default since v1.12). The WAL and VLog flush windows became upper bounds: a lone writer is synced at once, concurrent writers after an idle gap of about one fdatasync; --group-commit=fixed restores the full-window wait. With an emulated 300 µs fdatasync on a macOS laptop (15 ms window, 128 B values): one writer’s P50 went from 16 ms to 0.45 ms, and 64 writers from 4.0K to 37.5K durable writes/s at P99 2.6 ms. It has not yet been measured on Linux NVMe. Raft read barrier (v1.12): a newly elected leader now waits for its no-op before serving local reads, and MGET passes the same barrier as GET.

C++ network front-end (experimental, opt-in). --net=cpp|uring|poll runs one event loop per core for the binary PUT GET DEL PING MPUT MGET commands, standalone mode only; reads that need disk are handed to goroutines. On a 4-CPU CI runner (measured before disk reads moved off the loop) it lowered read P50 (154 vs 286 µs) but had a worse read P99 and ~12% lower batch-write throughput than the default Go listener. It does not serve the search commands. It is not faster overall, so --net=go stays the default.

Lone-writer PUT P50
0.45 ms
was 16 ms · emulated 300 µs sync
Batch writes
3.54M/s
macOS, 1M keys · was 1.45M
--net=cpp
opt-in
experimental, not faster overall
Every figure above has its conditions in the main repo's BENCHMARK_RESULTS.md and CHANGELOG.md.
Measured numbers
Where it fits

Built for teams where microseconds move money.

We don't pretend to be a general-purpose database. VeltrixDB is a point-lookup engine first — if you're running one of these workloads at scale, this was built for you.

01 — AdTech & Real-Time Bidding

User profile lookups inside the 50ms RTB budget.

Fetch the user profile, score the bid, write the impression — at high request rates. Point lookups are the entire workload. Your RAM budget and bare-metal NVMe match the architecture perfectly.

User profilesBid scoringImpression writesDSP / SSP
02 — HFT & Crypto Exchanges

Sharded architecture, durable state.

Position state and risk checks that must survive a restart. 8192 index shards keep lock contention low, every write is fsynced before the ack, and CAS / INCR are shard-locked and safe under concurrency. Measure your own tail before you put it on a latency-critical path.

PositionsRisk stateBalancesTick storage
03 — Persistent caches & session stores

Redis-class speed, without RAM-class bills.

When your dataset has outgrown the budget of "keep everything in RAM," but hot keys still need to be served from memory. A DRAM index over NVMe values holds far more data per dollar of RAM — persistent and durable, rebuilt from the WAL checkpoint on restart.

Session storesHot cachesCDN edgeFeature lookups
04 — Fraud detection & rate limiting

Continuous writes, instantaneous lookups.

Stream transactions in, score them against history, decide fast. Values are written once, with no LSM compaction rewriting them, so NVMe endurance survives the write rate; batched MPUT keeps ingest cheap.

Fraud scoringRate limitsVelocity checksUser history
Global Infrastructure

One binary. Any cloud. Anywhere.

Deploy on GKE, EKS, AKS, or bare metal with a single Helm command, on your own infrastructure. Same binary everywhere. No specialist hire, no lock-in.

Run it where your data lives

Your regions, your VPC, your NVMe.

Inside a cluster: Raft consensus (quorum-committed writes), or replicated mode with eventual, quorum, or strong consistency, and rack-aware placement that keeps copies of a partition in different zones (--rack-id). Across regions: repl-ship forwards the change-data-capture stream to another cluster. Self-hosted only — there is no managed service today.

3
Replication modes
4
Deploy targets
GCP
Google Cloud · GKE
n2-highmem-96
Local NVMe SSDs
AWS
Amazon · EKS
i3en / im4gn
Local NVMe
AZURE
Microsoft · AKS
Lsv3 NVMe series
Full StorageClass
SELF-HOST
Bare metal
Direct NVMe · any Linux
No hypervisor overhead
~/veltrixdb · zsh
$ helm repo add veltrixdb https://charts.veltrixdb.io
"veltrixdb" has been added to your repositories
$ helm install veltrixdb veltrixdb/veltrixdb \
    --namespace veltrixdb --create-namespace
# the chart (separate repo) deploys:
# StatefulSet · nvme-prep DaemonSet (formats XFS)
# NVMe StorageClass · ServiceMonitor · PrometheusRule
# PodDisruptionBudget (minAvailable: 2)
$
⎈ Kubernetes-native
StatefulSet · anti-affinity · PDB
⚓ Helm chart
one command · full values.yaml
🤖 K8s operator
rolling upgrades · reshard · self-heal · separate repo
📊 Prometheus + Grafana
70+ metric families · alert rules · dashboards
Honest fit check

What it won't do — and what it needs.

We'd rather lose the deal than oversell. VeltrixDB is a scalpel, not a Swiss Army knife — here's the truth about hardware, query patterns, and memory before we get on a call.

Hard requirements we won't bend on.

Last updated · October 2026
⚠
Bare-metal NVMe or local SSD only
Optimised for direct-attached NVMe on Linux (O_DIRECT, raw block devices supported). Not recommended for AWS EBS, Azure managed disks, or any network-attached storage — they break the latency model.
⚠
Point lookups first
Purpose-built for high-throughput GET / PUT / DEL at scale. Ordered scans exist (RANGE, SCANCUR, backed by a skiplist at ~90 B/key), and so do vector, BM25 and hybrid search — but no joins, no SQL, and no facets or aggregations. No Redis (RESP) protocol — clients use our text or binary protocol and SDKs.
⚠
RAM budget for the index
Every key's index record lives in DRAM. The native index measured ~142 B/key settled RSS at 5M keys (168 B/key with the Go map), plus ~90 B/key for the ordered index unless you pass --disable-ordered-index, plus your cache. Size with your own key lengths — you will not run a large keyspace on a t3.medium.
⚠
Search indexes live in RAM
HNSW graphs and the BM25 index are in memory (~0.4–3.4 KB per 768-dim vector, by layout) and are rebuilt at every start; searches are refused until the rebuild ends. Tested to 100K real vectors — nothing at 10M+ yet.
⚠
Kubernetes pieces are separate repos
The Helm chart (VeltrixDB-Helm-Chart) and the operator (VeltrixDB-Kubernetes-Operator) are published from their own repositories, not the server’s; check their own docs for what each version deploys. Adding a node means every node must list it in --peers — gossip does not add members.
⚠
Encryption has known gaps
--encrypt-at-rest encrypts values (AES-256-GCM), not keys. There is no key rotation: one key per data directory, loaded from an env var or file. Point-in-time-recovery archives hold values decrypted, so protect that location.
Linux for production (macOS fsync is not power-loss safe) · x86-64-v2 CPU baseline on amd64 cgo builds · vm.max_map_count ≥ 262144 for the native index · 3 nodes for replicated production Talk to an architect before you commit →
60-SECOND FIT CHECK

Five questions. An honest verdict.

The same qualification we run on every demo call — answered here so you don't need the call to find out we're the wrong tool.

0 / 5 answered
01Dominant access pattern?
02Working-set size?
03Strictest latency SLA?
04Write durability model?
05Must survive a full zone outage with zero data loss?

Ran the fit check? Pressure-test us on your workload.

30 minutes with an engineer, not a salesperson · We will tell you if we are the wrong tool