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).
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.
--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:
| Resource | Purpose |
|---|---|
StatefulSet | VeltrixDB pods with stable per-node hostnames |
nvme-prep DaemonSet | Formats XFS and handles kubelet mount-namespace isolation on GKE/EKS/AKS |
StorageClass | Local NVMe PersistentVolumes |
ServiceMonitor | Per-pod Prometheus scraping |
PodDisruptionBudget | minAvailable: 2 for safe rolling upgrades |
PrometheusRule | Alerting 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.