VeltrixDB Docs
v1.16 GitHub FAQ Quickstart

Installation

VeltrixDB can be installed four ways: a Docker image for local testing, a source build for development, a Helm chart for Kubernetes, or the Kubernetes Operator for fully managed clusters.

Docker

The fastest way to try VeltrixDB. The published image requires no build step:

docker run -p 9000:9000 ghcr.io/veltrixdb/veltrixdb:latest

This starts a single standalone node listening on 9000 (add -p 2112:2112 for metrics and health checks). Release images are tagged per release, e.g. ghcr.io/veltrixdb/veltrixdb:v1.16, plus latest. It's suitable for local development and protocol testing, not for production NVMe throughput — for that, run on bare metal or Kubernetes with real local NVMe disks attached.

New in v1.6 The image is built with CGO_ENABLED=1 on gcr.io/distroless/cc-debian12 (glibc, no shell), so it carries the off-heap native index. The io_uring VLog write bridge is compiled in but stays off unless you set VELTRIXDB_URING_BRIDGE=on or sqpoll; under Kubernetes' RuntimeDefault seccomp profile io_uring_setup is blocked and an opted-in bridge falls back to pwrite. Build with --build-arg CGO_ENABLED=0 for the old fully static, pure-Go image (Go map index).

Set vm.max_map_count on the host The native index mmaps its large arrays individually, so at large key counts the host (or Kubernetes node) needs vm.max_map_count ≥ 262144; below that an insert can fail with ENOMEM. A container cannot set it — apply scripts/sysctl.conf on the host, e.g. sudo sysctl -w vm.max_map_count=262144.

Build from source

Requires Go 1.19+ (go.mod) for a pure-Go build; the Docker image builds with Go 1.22. A default go build uses cgo, which needs a C++ compiler; the native index and the C++ network front-end also need Go 1.21+ (older toolchains fall back to the Go map and --net=go only); on Linux the C++ network front-end also links liburing (install liburing-dev, or add -tags vxnf_nouring for a poll()-only front-end). Set CGO_ENABLED=0 for a pure-Go build with no C++ at all (Go map index, no --net=cpp).

git clone https://github.com/VeltrixDB/veltrixdb
cd veltrixdb
go build ./...                  # cgo build (default): native index
CGO_ENABLED=0 go build ./...    # pure-Go build: Go map index, no C++
go run ./cmd/server -addr :9000 -data ./dev-data -cache 256

For release artifacts, scripts/build.sh builds the C++ library and the Go binaries together (Linux, requires CMake and liburing); ./scripts/build.sh --go-only skips the CMake step. The cgo directives target a portable -march=x86-64-v2 baseline on amd64; scripts/build.sh re-adds -march=native when it builds on the target machine.

To build the standalone binary and additional tooling (operator CLI, backup tool):

go build -o veltrix ./cmd/veltrix        # cluster CLI: status, nodes, top, put/get, backup
go build -o veltrixdb-backup ./cmd/backup # backup/restore tool

Run the test suite before contributing changes:

go test ./...            # unit tests
./tests/e2e/run_all.sh   # e2e tests (builds and starts its own servers; port 9000 must be free)
./scripts/bench.sh       # benchmark with pass/fail gates

Helm chart

The Helm chart deploys a full production topology on Kubernetes: a StatefulSet with stable per-node hostnames, an nvme-prep DaemonSet that formats and prepares local NVMe disks, a StorageClass for local NVMe PersistentVolumes, a ServiceMonitor for Prometheus scraping, a PodDisruptionBudget, and a PrometheusRule. The chart lives in its own repository (VeltrixDB-Helm-Chart); the server repo's copy of the rules, monitoring/prometheus-rules.yaml, has 10 alerts in v1.16 (write throttle, GC stalled, VLog read errors, scrub corruption, low cache hit rate, read P99, node failed, cluster shrank, disk full, restart; New on main after v1.16 — ships in the next release 24, adding search, raft and replication-recovery alerts) — check the chart's own rules for anything beyond these.

helm repo add veltrixdb https://charts.veltrixdb.io
helm repo update

helm install veltrixdb veltrixdb/veltrixdb \
  --namespace veltrixdb \
  --create-namespace

Verify the deployment:

kubectl get pv | grep local-nvme
kubectl get pods -n veltrixdb -l app.kubernetes.io/name=veltrixdb
kubectl port-forward -n veltrixdb veltrixdb-0 9000:9000 &
echo PING | nc 127.0.0.1 9000
# Expected: PONG

See the Helm Chart reference for the full values table, including cache sizing, TLS, encryption, quotas, and raw block-device VLog options.

Kubernetes Operator

The Operator lives in its own repository (VeltrixDB-Kubernetes-Operator); the paths below are relative to a checkout of it. It manages VeltrixDB clusters through a VeltrixCluster Custom Resource. It creates and owns the StatefulSet, Services, ConfigMap, and PVCs; automatically reshards when replica count changes; self-heals failed pods; and performs rolling upgrades.

Deploy the NVMe mount keeper first — it ensures real NVMe XFS filesystems are mounted at the PV source paths before kubelet binds them into the pod (skipping this causes ENOSPC on the first WAL write):

kubectl apply -f config/manager/nvme-mount-keeper.yaml
kubectl rollout status daemonset/nvme-mount-keeper -n veltrixdb

Install the CRDs, then deploy the operator:

kubectl apply -f config/crd/bases/
kubectl apply -f config/manager/manager.yaml

Create a cluster:

apiVersion: veltrixdb.io/v1alpha1
kind: VeltrixCluster
metadata:
  name: my-cluster
  namespace: veltrixdb
spec:
  replicas: 3
  image: ghcr.io/veltrixdb/veltrixdb:v1.16
  disksPerNode: 8
  cacheSizeMB: 262144
  walFlushWindowMs: 15
  vlogFlushWindowMs: 15
kubectl apply -f veltrixcluster.yaml
kubectl get veltrixcluster -n veltrixdb

See the Kubernetes Operator reference for the full spec, including at-rest encryption, audit logging, per-namespace quotas, the admin API/UI surface, and the optional chaos-engineering sidecar.

GKE node pools require the NVME interface VeltrixDB needs 8 independent NVMe queues. Without --local-ssd-interface=NVME, GKE merges all local SSDs into a single RAID-0 device and you lose the parallel I/O benefit:
gcloud container node-pools create veltrixdb-pool \
  --cluster=my-cluster \
  --zone=us-central1-a \
  --machine-type=n2-highmem-64 \
  --num-nodes=3 \
  --local-ssd-count=8 \
  --local-ssd-interface=NVME \
  --disk-size=100GB

What gets installed (Helm and Operator)

Both the Helm chart and the Operator provision the same core set of Kubernetes resources:

ResourcePurpose
StatefulSetVeltrixDB pods with stable per-node hostnames
nvme-prep DaemonSetFormats XFS and handles kubelet mount-namespace isolation on GKE/EKS/AKS
StorageClassLocal NVMe PersistentVolumes
ServiceMonitorPer-pod Prometheus scraping
PodDisruptionBudgetminAvailable: 2 for safe rolling upgrades
PrometheusRuleAlerting rules; the server repo's copy (monitoring/prometheus-rules.yaml) has 10 alerts

The Operator additionally handles auto-reshard on replica-count changes and self-healing pod replacement as part of its reconcile loop.