⚙️ VelesDB Configuration

August 17, 2026 · View on GitHub

Version 5.1.0 — Last updated: 2026-08-08

Complete guide for configuring VelesDB via configuration file, environment variables, and runtime parameters.

See also: SERVER_SECURITY.md for the server operations guide (authentication, TLS, graceful shutdown, health endpoints).


Table of Contents

  1. Overview
  2. velesdb.toml File
  3. Environment Variables
  4. Priority Order
  5. Complete Reference
  6. Usage Examples
  7. Validation and Errors

Overview

VelesDB supports 3 levels of configuration:

LevelSourcePriorityPersistence
Filevelesdb.tomlLow✅ Disk
EnvironmentVELESDB_*MediumSession
RuntimeAPI / REPL / VelesQLHighRequest

File Search Paths

VelesConfig::load() (used when no explicit path is given) only ever looks at ./velesdb.toml in the current working directory. There is no ~/.config/velesdb/, %APPDATA%\velesdb\, or /etc/velesdb/ search — if you previously read that here, it described a search path that was never implemented. If no ./velesdb.toml is found, core defaults are used.

To point at a file anywhere else, pass it explicitly:

BinaryFlagEnv var
velesdb-server--config <path>VELESDB_CONFIG
velesdb (CLI)--config <path> (global — REPL and every one-shot command)VELESDB_CONFIG

Both binaries can load the same file, but only the engine sections — [search], [hnsw], [storage], [limits], [quantization], [wal_batch] — reach VelesConfig and, via Database::open_with_config, the running engine. Every other top-level table is silently dropped before VelesConfig ever sees it — most importantly [server], [auth], [tls], [cors], which stay exclusively velesdb-server's own transport config. This matters because VelesConfig also has its own same-named [server]/[logging] fields (for standalone/embedded use), which don't mean the same thing: a perfectly legitimate velesdb-server --config value like [server] port = 443 (its HTTP bind port, e.g. behind setcap) would otherwise land in VelesConfig's own server.port too and get rejected by its >= 1024 validation rule — a startup failure with nothing to do with the value you actually set. Both binaries filter the file down to the engine sections before parsing it as VelesConfig, so this can't happen.

VELESDB_* environment variables still layer on top of the (filtered) file, same as VelesConfig::load/load_from_path — e.g. VELESDB_LIMITS_MAX_COLLECTIONS=5 overrides a [limits] max_collections value from the file, and velesdb-server's own VELESDB_PORT/ VELESDB_HOST/... env vars (mapped to its transport Args, not to VelesConfig) keep working exactly as before.

Semantics are fail-fast: an explicit --config/VELESDB_CONFIG path that is missing, malformed, or fails validation aborts startup (server) or the command (CLI) with the typed ConfigError — it never silently falls back to defaults. Omitting the flag entirely is unaffected: both binaries behave exactly as before this option was wired (core defaults, or ./velesdb.toml if present).

# Server: engine + transport settings from one file
velesdb-server --config /etc/velesdb/velesdb.toml
VELESDB_CONFIG=/etc/velesdb/velesdb.toml velesdb-server

# CLI: applies to the REPL...
velesdb --config ./velesdb.toml repl ./my_database
# ...and to one-shot commands (flag may come before or after the subcommand)
velesdb collection create ./my_database docs --dimension 768 --config ./velesdb.toml

Some other VelesDB surfaces (Tauri desktop shell, mobile bindings, the Python SDK's VelesConfigOptions, and the LangChain/LlamaIndex integrations) do not yet accept a VelesConfig at open time — tracked in issue #1549.


velesdb.toml File

Minimal Example

# velesdb.toml - Configuration minimale
[search]
default_mode = "balanced"

[storage]
data_dir = "./data"

Full Example

# =============================================================================
# VelesDB Configuration File
# Version: 5.1.0
# =============================================================================

# -----------------------------------------------------------------------------
# SEARCH CONFIGURATION
# Contrôle le comportement par défaut des recherches vectorielles
# -----------------------------------------------------------------------------
[search]
# Mode de recherche par défaut
# Valeurs: "fast" | "balanced" | "accurate" | "perfect"
# Default: "balanced"
default_mode = "balanced"

# Valeur ef_search par défaut (override le mode si spécifié)
# Range: 16 - 4096
# Default: null (utilise la valeur du mode)
# ef_search = 128

# Nombre maximum de résultats par requête
# Range: 1 - 10000
# Default: 1000
max_results = 1000

# Timeout des requêtes en millisecondes
# Range: 100 - 300000 (5 minutes max)
# Default: 30000 (30 secondes)
query_timeout_ms = 30000

# -----------------------------------------------------------------------------
# HNSW INDEX CONFIGURATION
# Paramètres de construction des index HNSW
# -----------------------------------------------------------------------------
[hnsw]
# Nombre de connexions par nœud (M parameter)
# Range: 4 - 128
# Default: "auto" (basé sur la dimension)
# Valeurs recommandées: 16 (petits datasets), 32-48 (général), 64+ (haute précision)
m = "auto"

# Taille du pool de candidats à la construction
# Range: 100 - 2000
# Default: "auto" (basé sur la dimension)
ef_construction = "auto"

# Nombre de couches HNSW (0 = auto-calculé)
# Range: 0 - 16
# Default: 0 (auto)
max_layers = 0

# -----------------------------------------------------------------------------
# STORAGE CONFIGURATION
# Gestion du stockage des données
# -----------------------------------------------------------------------------
[storage]
# Répertoire de données principal
# Default: "./velesdb_data"
data_dir = "./velesdb_data"

# Mode de stockage des vecteurs
# Valeurs: "mmap" | "memory"
# - mmap: Fichiers mappés en mémoire (recommandé pour grands datasets)
# - memory: Tout en RAM (plus rapide, limité par RAM disponible)
# Default: "mmap"
storage_mode = "mmap"

# Taille maximale du cache mmap en mégaoctets
# Range: 64 - 65536 (64 GB max)
# Default: 1024 (1 GB)
mmap_cache_mb = 1024

# Alignement mémoire pour les vecteurs (octets)
# Valeurs: 32 | 64 | 128
# Default: 64 (optimal pour la plupart des CPUs)
vector_alignment = 64

# -----------------------------------------------------------------------------
# LIMITS CONFIGURATION
# Limites de sécurité pour prévenir les erreurs utilisateur
# -----------------------------------------------------------------------------
[limits]
# Dimension maximale des vecteurs
# Range: 1 - 65536
# Default: 4096
max_dimensions = 4096

# Nombre maximum de vecteurs par collection
# Range: 1000 - 1000000000 (1 milliard)
# Default: 100000000 (100 millions)
max_vectors_per_collection = 100000000

# Nombre maximum de collections
# Range: 1 - 10000
# Default: 1000
max_collections = 1000

# Taille maximale du payload JSON par point (octets)
# Range: 1024 - 16777216 (16 MB)
# Default: 1048576 (1 MB)
max_payload_size = 1048576

# Nombre maximum de vecteurs pour le mode "perfect" (bruteforce)
# Au-delà, une erreur est retournée pour protéger contre les timeouts
# Range: 1000 - 10000000
# Default: 500000
max_perfect_mode_vectors = 500000

# -----------------------------------------------------------------------------
# SERVER CONFIGURATION (velesdb-server uniquement)
# -----------------------------------------------------------------------------
[server]
# Adresse d'écoute
# Default: "127.0.0.1"
host = "127.0.0.1"

# Port d'écoute
# Range: 1024 - 65535
# Default: 8080
port = 8080

# Répertoire de données (collections, WAL, index)
# Default: "./velesdb_data"
data_dir = "./velesdb_data"

# Timeout de drain des connexions lors de l'arrêt gracieux (secondes)
# Range: 1 - 300
# Default: 30
shutdown_timeout_secs = 30

# Rate limit: requêtes max par seconde par IP (0 = désactivé)
# Default: 100
rate_limit = 100

# Nombre de workers (threads)
# Range: 1 - 256
# Default: nombre de CPUs
workers = 0  # 0 = auto-detect

# Taille maximale du body HTTP (octets)
# Range: 1048576 - 1073741824 (1 GB max)
# Default: 104857600 (100 MB)
max_body_size = 104857600

# Activer CORS
# Default: false
cors_enabled = false

# Origines CORS autorisées (si cors_enabled = true)
# Default: ["*"]
cors_origins = ["*"]

# -----------------------------------------------------------------------------
# AUTHENTICATION (velesdb-server uniquement)
# Voir SERVER_SECURITY.md pour le guide complet
# -----------------------------------------------------------------------------
[auth]
# Liste des clés API autorisées (Bearer tokens)
# Lorsque vide ou absent, l'authentification est désactivée (mode dev local)
# Les endpoints /health et /ready sont toujours publics
# Default: [] (désactivé)
# api_keys = ["my-secret-key-1", "my-secret-key-2"]

# -----------------------------------------------------------------------------
# TLS CONFIGURATION (velesdb-server uniquement)
# Voir SERVER_SECURITY.md pour le guide complet
# -----------------------------------------------------------------------------
[tls]
# Chemin vers le fichier certificat PEM
# Les deux champs (cert + key) doivent être définis ensemble
# Default: null (HTTP en clair)
# cert = "/path/to/cert.pem"

# Chemin vers le fichier clé privée PEM
# Default: null (HTTP en clair)
# key = "/path/to/key.pem"

# -----------------------------------------------------------------------------
# LOGGING CONFIGURATION
# -----------------------------------------------------------------------------
[logging]
# Niveau de log
# Valeurs: "error" | "warn" | "info" | "debug" | "trace"
# Default: "info"
level = "info"

# Format de log
# Valeurs: "text" | "json"
# Default: "text"
format = "text"

# Fichier de log (vide = stdout)
# Default: "" (stdout)
file = ""

# -----------------------------------------------------------------------------
# QUANTIZATION CONFIGURATION
# Compression des vecteurs
# -----------------------------------------------------------------------------
[quantization]
# Type de quantization par défaut pour les nouvelles collections
# Valeurs: "none" | "sq8" | "binary"
# Default: "none"
default_type = "none"

# Activer le reranking f32 après recherche quantifiée
# Améliore le recall au prix d'une latence légèrement supérieure
# Default: true
rerank_enabled = true

# Nombre de candidats pour le reranking (multiplicateur de k)
# Range: 1 - 10
# Default: 2
rerank_multiplier = 2

# -----------------------------------------------------------------------------
# UPDATE CHECK (v1.9.2+)
# Non-blocking startup check for new versions. No PII collected.
# -----------------------------------------------------------------------------
[update_check]
# Enable/disable update check (default: true)
# Can also be disabled via VELESDB_NO_UPDATE_CHECK=1
enabled = true

# Endpoint URL (default: https://velesdb.com/api/check)
# endpoint = "https://velesdb.com/api/check"

# Timeout in milliseconds (default: 2000)
# timeout_ms = 2000

# -----------------------------------------------------------------------------
# PREMIUM FEATURES (nécessite velesdb-premium)
# -----------------------------------------------------------------------------
[premium]
# Clé de licence (ou utiliser VELESDB_LICENSE_KEY env var)
# license_key = "VELES-XXXX-XXXX-XXXX-XXXX"

# Activer le hot-reload de la configuration (Premium)
# Default: false
hot_reload = false

# Profil de recherche prédéfini (Premium)
# Valeurs: "default" | "low_latency" | "accurate" | "memory_optimized"
# Default: "default"
# profile = "default"

Environment Variables

All options can be set via environment variables with the VELESDB_ prefix:

VariableTOML EquivalentExample
VELESDB_SEARCH_DEFAULT_MODEsearch.default_modebalanced
VELESDB_SEARCH_EF_SEARCHsearch.ef_search256
VELESDB_HNSW_Mhnsw.m48
VELESDB_HNSW_EF_CONSTRUCTIONhnsw.ef_construction600
VELESDB_STORAGE_DATA_DIRstorage.data_dir/var/lib/velesdb
VELESDB_STORAGE_MODEstorage.storage_modemmap
VELESDB_HOSTserver.host0.0.0.0
VELESDB_PORTserver.port8080
VELESDB_DATA_DIRserver.data_dir/var/lib/velesdb
VELESDB_RATE_LIMITserver.rate_limit100
VELESDB_API_KEYSauth.api_keyskey1,key2,key3 (comma-separated)
VELESDB_TLS_CERTtls.cert/etc/ssl/cert.pem
VELESDB_TLS_KEYtls.key/etc/ssl/key.pem
VELESDB_LOGGING_LEVELlogging.leveldebug
VELESDB_LICENSE_KEYpremium.license_keyVELES-...
VELESDB_NO_UPDATE_CHECKupdate_check.enabled1 (disables)
VELESDB_CONFIGConfig file path/etc/velesdb/velesdb.toml

Name Mapping

The mapping follows this rule:

VELESDB_{SECTION}_{KEY} (uppercase, underscores)
→ section.key (lowercase, underscores preserved)

Examples

# Linux/macOS
export VELESDB_SEARCH_DEFAULT_MODE=accurate
export VELESDB_SERVER_PORT=9090
export VELESDB_LOGGING_LEVEL=debug

# Windows PowerShell
$env:VELESDB_SEARCH_DEFAULT_MODE = "accurate"
$env:VELESDB_SERVER_PORT = "9090"

# Docker
docker run -e VELESDB_SERVER_HOST=0.0.0.0 -e VELESDB_SERVER_PORT=8080 velesdb

Priority Order

Configuration follows this priority order (from lowest to highest):

1. Default values (hardcoded)

2. velesdb.toml file

3. VELESDB_* environment variables

4. CLI parameters (--host, --port, --data-dir, --tls-cert, --tls-key)

5. Runtime override (REPL \set, VelesQL WITH, API params)

--config/VELESDB_CONFIG isn't a level in this chain — it selects which file fills level 2, for both velesdb-server and the velesdb CLI. See File Search Paths above for its exact semantics.

Resolution Example

# velesdb.toml
[search]
default_mode = "balanced"
ef_search = 128
# Environment
export VELESDB_SEARCH_EF_SEARCH=256
-- VelesQL
SELECT * FROM docs WHERE vector NEAR $v WITH (ef_search = 512);

Result: The query uses ef_search = 512 (runtime override wins).

Any WITH (ef_search = N) value is passed through as the requested budget — N is sent to HNSW (clamped to at least k, and still subject to the standard dataset-size scaling), not snapped to a coarse named profile. (Updated 2026-06-14.)


Complete Reference

KeyTypeDefaultDescription
default_modestring"balanced"Default search mode
ef_searchint?nullef_search override (if null, uses mode value)
max_resultsint1000Maximum results per query
query_timeout_msint30000Timeout in ms

Section [hnsw]

KeyTypeDefaultDescription
mint|"auto""auto"Connections per node
ef_constructionint|"auto""auto"Construction pool size
max_layersint0Max layers (0=auto)

Section [storage]

KeyTypeDefaultDescription
data_dirstring"./velesdb_data"Data directory
storage_modestring"mmap"Mode: mmap or memory
mmap_cache_mbint1024mmap cache in MB
vector_alignmentint64Memory alignment

Section [limits]

KeyTypeDefaultDescription
max_dimensionsint4096Max dimension
max_vectors_per_collectionint100000000Max vectors/collection
max_collectionsint1000Max collections
max_payload_sizeint1048576Max payload (bytes)
max_perfect_mode_vectorsint500000Bruteforce limit

All five [limits] fields are enforced at runtime (since 2026-06-14), not only range-validated at load: max_dimensions / max_collections at collection creation, and max_vectors_per_collection / max_payload_size / max_perfect_mode_vectors at the ingest/search boundary. An operation that would exceed a cap is rejected with a GuardRail error (VELES-027) naming the actual value, the cap, and the limits.<field> to raise — the engine never silently clamps. The defaults are permissive, so typical workloads are unaffected.

Section [server]

KeyTypeEnv varCLI flagDefaultDescription
hoststringVELESDB_HOST--host"127.0.0.1"Listen address
portintVELESDB_PORT--port8080Port
data_dirstringVELESDB_DATA_DIR--data-dir"./velesdb_data"Data directory
shutdown_timeout_secsint30Connection drain timeout (seconds)
workersint0Workers (0=auto)
max_body_sizeint104857600Max body (bytes)
rate_limitintVELESDB_RATE_LIMIT--rate-limit100Max req/s per IP (0=disabled)
cors_enabledboolfalseEnable CORS
cors_originsarray["*"]CORS origins

Section [auth]

KeyTypeEnv varCLI flagDefaultDescription
api_keysarrayVELESDB_API_KEYS[] (disabled)Authorized Bearer API keys

VELESDB_API_KEYS accepts comma-separated keys: key1,key2,key3. When the list is empty, authentication is disabled (local dev mode). The /health and /ready endpoints are always public.

Section [tls]

KeyTypeEnv varCLI flagDefaultDescription
certstring?VELESDB_TLS_CERT--tls-certnullPEM certificate path
keystring?VELESDB_TLS_KEY--tls-keynullPEM private key path

Both fields must be set together. If neither is set, the server uses plain HTTP. See SERVER_SECURITY.md for certificate generation.

Section [logging]

KeyTypeDefaultDescription
levelstring"info"Log level
formatstring"text"Format: text or json
filestring""File (empty=stdout)

Section [quantization]

KeyTypeDefaultDescription
default_typestring"none"Default type
rerank_enabledbooltrueEnable reranking
rerank_multiplierint2Candidate multiplier

Section [update_check]

KeyTypeDefaultDescription
enabledbooltrueEnable startup update check
endpointstring"https://velesdb.com/api/check"Update check endpoint URL
timeout_msu642000Timeout in milliseconds

Privacy: Only sends version, OS, architecture, and a non-reversible SHA256 instance hash. No personal data collected. Disable with VELESDB_NO_UPDATE_CHECK=1 or enabled = false.

Section [premium]

KeyTypeDefaultDescription
license_keystring?nullLicense key
hot_reloadboolfalseConfig hot-reload
profilestring"default"Predefined profile

Usage Examples

Local Development

[search]
default_mode = "fast"  # Latence minimale pour dev

[storage]
data_dir = "./dev_data"
storage_mode = "memory"  # Tout en RAM

[logging]
level = "debug"

Production - High Performance

[search]
default_mode = "balanced"
query_timeout_ms = 10000

[hnsw]
m = 48
ef_construction = 600

[storage]
data_dir = "/var/lib/velesdb"
storage_mode = "mmap"
mmap_cache_mb = 4096
vector_alignment = 64

[server]
host = "0.0.0.0"
port = 8080
workers = 16

[logging]
level = "warn"
format = "json"
file = "/var/log/velesdb/velesdb.log"

Production - High Precision (Legal/Medical)

[search]
default_mode = "accurate"
query_timeout_ms = 60000

[hnsw]
m = 64
ef_construction = 800

[limits]
max_perfect_mode_vectors = 1000000  # Autoriser bruteforce sur gros datasets

[logging]
level = "info"
format = "json"

Edge / IoT - Limited Resources

[search]
default_mode = "fast"

[hnsw]
m = 16
ef_construction = 200

[storage]
storage_mode = "mmap"
mmap_cache_mb = 128

[quantization]
default_type = "binary"  # 32x compression

[limits]
max_vectors_per_collection = 100000
max_dimensions = 768

Docker / Kubernetes

[server]
host = "0.0.0.0"  # Écouter sur toutes les interfaces
port = 8080

[storage]
data_dir = "/data"  # Volume monté

[logging]
level = "info"
format = "json"  # Pour collecteurs de logs

Validation and Errors

Startup Validation

VelesDB validates the configuration at startup and displays errors clearly:

ERROR: Configuration validation failed:
  - search.default_mode: invalid value "ultra_fast", expected one of: fast, balanced, accurate, perfect
  - hnsw.m: value 256 exceeds maximum 128
  - storage.data_dir: directory "/nonexistent" does not exist and cannot be created

Warnings

Some configurations generate warnings without blocking startup:

WARN: search.ef_search=2048 is very high, may cause slow queries
WARN: limits.max_perfect_mode_vectors=5000000 allows slow bruteforce on large datasets
WARN: premium.hot_reload=true but no valid license key found

Validating a Config File

There is no dedicated velesdb config validate/show/init subcommand. Instead, --config itself doubles as the validation entry point: pointing either binary at a file validates it fail-fast, before anything else runs.

# CLI — fails immediately if the file is missing or invalid, before opening
# any database (works with any subcommand, e.g. `info`):
velesdb --config ./velesdb.toml info ./my_database

# Server — fails immediately at startup, before binding a socket:
velesdb-server --config ./velesdb.toml

A missing path prints config file not found: <path>; an invalid value prints the typed ConfigError (e.g. Invalid configuration value for 'limits.max_collections': ...) naming the offending key.


Rate Limiting

VelesDB Server includes per-IP rate limiting backed by a token-bucket algorithm (tower-governor). The rate limiter uses SmartIpKeyExtractor, which inspects x-forwarded-for, x-real-ip, and forwarded headers before falling back to the peer IP, making it safe behind reverse proxies.

Configuration

SourceSettingExample
CLI--rate-limit Nvelesdb-server --rate-limit 200
EnvironmentVELESDB_RATE_LIMITVELESDB_RATE_LIMIT=200
TOML[server] rate_limitrate_limit = 200
  • Default: 100 (requests per second per IP)
  • Disable: Set to 0 to disable rate limiting entirely

Behavior

When a client exceeds the limit, the server responds with HTTP 429 Too Many Requests and includes rate-limit headers:

HeaderDescription
x-ratelimit-limitMaximum requests allowed per second
x-ratelimit-remainingRemaining requests in the current window
x-ratelimit-afterSeconds until the bucket refills
retry-afterSeconds to wait before retrying (only on 429)

A background thread prunes stale IP entries from the rate limiter map every 60 seconds.

Examples

# Production: 200 req/s per IP
[server]
rate_limit = 200

# Development: disabled
[server]
rate_limit = 0
# CLI override
velesdb-server --rate-limit 50

# Environment override
VELESDB_RATE_LIMIT=0 velesdb-server

Schema Versioning

Each collection's config.json includes a schema_version field (type u32) that tracks the on-disk format version. This prevents a newer VelesDB from writing data that an older version cannot read.

Behavior

ConditionResult
schema_version absent or 0Treated as 1 (backward compatibility with pre-versioned collections)
schema_version equals currentNormal operation
schema_version > currentError VELES-036 IncompatibleSchemaVersion -- upgrade VelesDB to open this collection
  • Current version: 1 (defined as CURRENT_SCHEMA_VERSION in crates/velesdb-core/src/collection/types.rs)
  • The version is validated at collection load time, before any data is read or modified
  • The VELES-036 error is not recoverable -- the only resolution is to upgrade VelesDB

config.json Example

{
  "dimension": 768,
  "distance_metric": "cosine",
  "schema_version": 1,
  "hnsw_config": {
    "m": 16,
    "ef_construction": 100
  }
}

Rust Implementation

Configuration Structure

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct VelesConfig {
    pub search: SearchConfig,
    pub hnsw: HnswConfig,
    pub storage: StorageConfig,
    pub limits: LimitsConfig,
    pub server: ServerConfig,
    pub logging: LoggingConfig,
    pub quantization: QuantizationConfig,
    pub premium: PremiumConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct SearchConfig {
    #[serde(default = "default_search_mode")]
    pub default_mode: SearchMode,
    pub ef_search: Option<usize>,
    #[serde(default = "default_max_results")]
    pub max_results: usize,
    #[serde(default = "default_query_timeout")]
    pub query_timeout_ms: u64,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SearchMode {
    Fast,
    Balanced,
    Accurate,
    Perfect,
}

// ... autres structs

Loading

use figment::{Figment, providers::{Env, Format, Toml}};

impl VelesConfig {
    pub fn load() -> Result<Self, ConfigError> {
        Figment::new()
            .merge(Toml::file("velesdb.toml").nested())
            .merge(Env::prefixed("VELESDB_").split("_"))
            .extract()
            .map_err(ConfigError::from)
    }
}

VelesDB Documentation — Last updated: 2026-08-08 · Applies to: velesdb-core 5.1.0