VeltrixDB Docs
v1.16 GitHub FAQ Quickstart

Limitations & Roadmap

These are real gaps in VeltrixDB today. We'd rather you know them upfront than discover them in production.

Honest limitations

Current as of v1.16 (2026-10-08, the latest release), checked against the server source. Gaps that v1.14 (2026-10-05) and v1.15 fixed are listed under Fixed in v1.14 and v1.15 — they still apply to an older install until you upgrade. Gaps already fixed on the main branch but not yet released are listed under Fixed on main after v1.16; on v1.16 and earlier they still apply.

Data loss on v1.16 and earlier: after an online backup, restart the node cleanly In every release v1.0–v1.16, an online backup (POST /admin/backup, veltrix backup) or POST /admin/checkpoint leaves the WAL flusher writing to an unlinked copy of wal.log. On standalone and replicated nodes, every write acknowledged afterwards is lost on a crash, power loss or SIGKILL until the node’s next clean restart (SIGTERM), which rewrites wal.log from the in-memory index; raft mode recovers those writes from the raft log. Workaround: after each online backup or checkpoint, restart the node cleanly as soon as you can. Fixed on main after v1.16 — ships in the next release see Backup & Restore.

Product and ecosystem

No Redis protocol (RESP) You can't point a Redis client at VeltrixDB. Workaround: the text protocol (nc-compatible) or one of the native SDKs; the command surface (PUT/GET/DEL, atomic ops) is close to Redis's. Roadmap: yes; nothing in the code implements it yet.
No managed cloud offering Self-hosted only. Workaround: the Helm chart or Operator (both in separate repositories) on your own cluster. Roadmap: planned.
No same-hardware comparison with other databases yet bench/compare holds a go-ycsb runner with Aerospike and ScyllaDB drivers and a vector benchmark, but the Aerospike / ScyllaDB paths are compile-checked only and nothing has been run side by side. The October 2026 numbers are VeltrixDB-only, mostly on one macOS laptop. Treat any cross-database claim as unmeasured.

Consistency and clustering

RANGE / SCANCUR and namespace scans are node-local They are served from the receiving node's own data and do not fan out. (Vector / text / hybrid search, QUERY and IDXQUERY do fan out.) Since v1.15 a running server never moves keys between nodes — raft applies the whole log on every node, and replicated mode sends every write to every peer — so a scan covers the whole keyspace, but only as fresh as that node: a raft follower can lag the leader, and a replicated node may not have applied a write accepted elsewhere yet. On v1.14 and earlier a node failure with the default --auto-rebalance=true moved keys off a node, after which its scans reflect only the keys it still holds (see Fixed in v1.14 and v1.15). Workaround: in raft mode, --linearizable-reads (followers redirect, and every read passes the ReadIndex fence); on v1.14 and earlier, --auto-rebalance=false, or fan out and merge client-side.
Replicated mode is not linearizable replicated mode has no single-writer ordering; replicas apply ops in arrival order (version vectors are reserved but unused, no conflict resolution runs). Anti-entropy re-sends un-acked ops only; it never compares keyspaces. --consistency defaults to eventual. Raft and replicated mode are mutually exclusive. On v1.13 and earlier a FAILED replica also stays failed until the primary restarts — fixed in v1.14; the fix keeps its catch-up state in memory, so a replica that was down when its primary restarted still misses the writes made before that restart. See Fixed in v1.14 and v1.15. Two clients writing one key through different nodes at the same time can leave the nodes holding different values for it permanently — still open. On v1.16 and earlier a replica that was down while its primary restarted never gets the writes and deletes made before that restart (Fixed on main after v1.16 — ships in the next release the acknowledgement watermark is persisted; a replica away longer than the tombstone retention is fully resynced and flagged FULL RESYNC, and a delete may survive on it). Workaround: raft mode for linearizable writes, or write each key through one node; on v1.13 and earlier, restart the primary after a replica outage and verify the replica.
Raft is a single group; on v1.16 and earlier snapshots are capped at 256 MB One log and one leader, so adding nodes adds fault tolerance, not write throughput. On v1.16 and earlier the server snapshot is the whole keyspace as key/value pairs, capped at 256 MB (a larger one is skipped and the log keeps growing), TTLs are not preserved in it, keys deleted while a follower lagged survive its restore, a restarted node re-applies its retained log (INCRs doubled), and SETIF version tokens differ between nodes. Fixed on main after v1.16 — ships in the next release see Fixed on main after v1.16. During a rolling upgrade from v1.16, a v1.16 follower can only receive a single-shot snapshot (≤ 256 MB, TTLs lost, deletes not applied) and SETIF / guarded TXN stay nondeterministic until every node is upgraded.
Membership changes: static on v1.16, online on main with limits On v1.16 and earlier a server builds its membership from --peers at startup; there is no runtime join/drain/remove command, and adding a node means restarting every node with the new --peers list. New on main after v1.16 — ships in the next release nodes are added and removed online (veltrix cluster add-node / remove-node, /admin/cluster/members; raft adds a learner and promotes it, replicated mode drains a node before removing it — see the runbook). What remains: one change at a time; node-to-node membership traffic, --join and every replicated-mode change need --cluster-secret-file or --cluster-mtls; replicated mode has no consensus, so a member that misses a change pulls it later (a window of disagreement during a partition); adding a replicated node copies every key from every member; a dead replicated node can only be force-removed, losing writes it acknowledged but never replicated; every node must run the new build before the first change; the Kubernetes operator still scales by restarting pods with a new --peers, which stops working once a change was made online. A node failure is a state change, not a membership change, so since v1.15 it never migrates keys. (On v1.13 and earlier tombstone reaping is also not coordinated with replica watermarks — fixed in v1.14.)
Distributed search asks every node Each vector / text / hybrid search, QUERY and IDXQUERY runs on all non-failed nodes, so cost grows with the cluster. A peer that does not answer within --search-timeout-ms fails the request (naming it) until the failure detector marks it failed, unless --search-allow-partial.
Search indexes are rebuilt at every start The HNSW graphs and BM25 inverted index live in RAM and are not persisted; at startup they are rebuilt from the persisted keys, and searches are refused until that finishes (search_ready=0 in INFO; /readyz does not wait). Budget restart time for large namespaces. Graph nodes, ids and upper layers stay on the Go heap even with GRAPH disk (~280–400 B per vector).
Tested to 100K real vectors Recall and latency are measured on GloVe-100 (100K vectors) and 10K synthetic 768-dim vectors; nothing at 10M+ has been run. Text search has no stemming, phrase queries or per-field weights; one document is at most 1 MiB; dimensions are 1–4096.

Security and data path

No encryption key rotation One key per data dir, loaded at startup, no per-record key version and no re-encrypt command. Changing the key means copying data through a client into a fresh node. See Disaster Recovery.
Audit log is not complete or tamper-evident It records engine writes only (not reads, admin calls, AUTH or TTL expiry), never fills the actor field, drops records when its channel is full, and is not hash-chained. On v1.13 and earlier it also covers only single-key PUT/DEL (not batches, transactions or atomic ops) — fixed in v1.14. See Fixed in v1.14 and v1.15. See also Security.
CDC live stream is lossy for slow subscribers /admin/cdc never blocks a writer: a subscriber whose buffer is full loses events and is disconnected (on v1.13 and earlier after 3 drops in total; since v1.14, 3 consecutive drops). repl-ship is last-write-wins with no back-pressure to the source. On v1.13 and earlier the stream also carries only single-key PUT/DEL — MPUT, coalesced pipelined PUTs, transactions and atomic ops reach a shipper only through the index-backed /admin/changes catch-up (last state only); fixed in v1.14. See Fixed in v1.14 and v1.15.
Backup caveats On v1.13 and earlier the offline veltrixdb-backup must never run against a live server's data dirs (it can truncate them) — use POST /admin/backup or veltrix backup; v1.14 and later refuse instead (data-dir lock, see Fixed in v1.14 and v1.15). On v1.16 and earlier writes made after an online backup are not crash-safe until a clean restart (see the warning above). With --raw-vlogs backups contain no VLog data, and backup does not pause GC. See Backup & Restore.
Monitoring gaps On v1.16 and earlier: no go_* or process_* metrics (so the shipped restart alert cannot fire) and no search or raft metrics (New on main after v1.16 — ships in the next release served, with 24 alerts checked against what a raft and a replicated server serve; still missing: process_* other than process_start_time_seconds is Linux only, search metrics count requests on the coordinating node only, CDC and audit drops are in /admin/stats only). On v1.13 and earlier replication_lag_nanoseconds / cluster_partition_migrations_total are also always 0 — fixed in v1.14. See Fixed in v1.14 and v1.15. See Monitoring.

Engine and front-end

The C++ network front-end is experimental New in v1.7 --net=cpp|uring|poll serves only the binary protocol's PUT GET DEL PING MPUT MGET, only in standalone mode, and refuses --auth-config; the text protocol, AUTH, TLS and every other command stay on the default --net=go. In CI measurements it lowered read P50 but had worse read P99 and ~12% lower batch-write throughput than the Go front-end, so it is opt-in and not faster overall. Workaround: keep --net=go unless you have measured a benefit on your hardware with scripts/net-bench.sh.
Some C++ components are not wired in The ART index, the priority io_uring scheduler, the C++ VLog reader (SQPOLL), the hugepage allocator, mlockall and the eBPF GC throttle exist under cpp/ but have no Go call site, so they do not run. The VLog read path is Go pread. The io_uring VLog write bridge is opt-in (VELTRIXDB_URING_BRIDGE, default off).

Fixed in v1.14 and v1.15 v1.14–v1.15

These were gaps in v1.13 and earlier (fixed in v1.14) or v1.14 and earlier (fixed in v1.15). Each item says which release fixed it: v1.14 (2026-10-05) or v1.15 (2026-10-07). v1.16 (2026-10-08) is the latest release. Until you upgrade, the older behaviour described in each item still applies.

Fixed on main after v1.16 Fixed on main after v1.16 — ships in the next release

These are fixed or added on the main branch and ship in the next release. On v1.16 and earlier the older behaviour described in each item still applies.

Shipped in v1.11–v1.12 New

v1.13 (2026-10-01) was documentation and test fixes over v1.12; v1.16 (2026-10-08) is the latest release, and what v1.14 and v1.15 fixed is listed under Fixed in v1.14 and v1.15. These used to be roadmap items or gaps:

Shipped in v1.6–v1.8

Shipped in v1.1.0

The following were listed as limitations before the v1.1.0 "distributed-completeness" release and are now implemented — they no longer belong on the list above:

What's coming

From the project changelog's "What's coming" section:

Track progress Follow GitHub Releases for updates on these items as they ship.