Configuration
Configure LivenDB for your deployment environment.
LivenDB reads liven.toml (and optionally liven.conf) from the current working directory, or the file passed with --config / LIVEN_CONFIG. Relative paths inside that file (storage.data_directory and the ZTNA certificate paths) resolve against the config file's directory, not the process CWD. Environment variables prefixed with LIVEN_ or LIVENDB_ override file values, and the embedded API accepts a programmatic LivenConfig. The precedence is built-in defaults → config file → environment variables.
Configuration Structure
- Server — network, ports, and connection settings
- Storage — data directory, segment size, and fsync policy
- Limits — streams, file descriptors, index budget, and scan limits
- Security — auth mode, master key, and mTLS/ZTNA certificates
Server Configuration
| Option | Type | Default | Description |
|---|---|---|---|
environment | String | "development" | Deployment environment: development, test, or production |
host | String | "127.0.0.1" | Bind address. In development/test the native listener is forced to 127.0.0.1. |
db_port | u16 | 43121 | Native TCP protocol port |
webui_port | u16 | 43120 | Web UI, REST, and WebSocket port |
max_connections | usize | 10000 | Concurrent native connections. Applied to the connection semaphore at startup and reported by status(). |
broadcast_capacity | usize | 4096 | Live-subscription broadcast capacity. Applied at startup and reported by status(). |
Storage Configuration
| Option | Type | Default | Description |
|---|---|---|---|
data_directory | String | "./data" | Directory for .liven segment files |
max_segment_size_mb | usize | 10 | Segment rollover size. This is the key that is actually read; put it under [storage], not [limits]. |
sync_mode | String | "always" | Only "always" is accepted: each flushed batch is fsynced before the write is acknowledged. Any other value makes the server refuse to start. |
Limits Configuration
| Option | Type | Default | Description |
|---|---|---|---|
max_concurrent_streams | usize | 32 | Maximum number of concurrent data streams |
max_open_file_descriptors | usize | 64 | Cached segment-file handles before eviction |
max_index_ram_mb | usize | auto | Primary-index budget. Auto-detected when absent; explicit 16 is treated as the legacy default and also auto-detects. |
max_scan_results | usize | 100000 | Caps live-key-index scans (stream scans without a limit). A live scan that would exceed the cap returns an error instead of silently truncating; historical (history()) and time-range scans are not capped. |
index_high_water_percent | u8 | 90 | Percentage of the index budget at which the high-water metric flips. Writes are still accepted until the hard limit. |
limits.max_segment_size_mb is parsed but never read. Use storage.max_segment_size_mb instead.
Retention Configuration
| Option | Type | Default | Description |
|---|---|---|---|
default_max_age_secs | u64 | 0 | Fallback max-age for streams without an override. 0 disables retention. |
check_interval_secs | u64 | 60 | Background retention pass interval. |
[retention.streams] | table | empty | Per-stream max-age overrides in seconds, e.g. events = 3600. |
Retention is segment-level: an inactive segment is deleted only when every live record in it is older than its stream's max-age. The active segment is left for rollover/compaction.
Security Configuration
| Option | Type | Default | Description |
|---|---|---|---|
mode | String | "auth_key" | auth_key or none. Development/test auto-selects none only when security mode is not explicitly configured. |
master_key | String | auto-generated | Seed for the first admin auth key. It is not a data-encryption key. Prefer LIVEN_SECURITY_MASTER_KEY. |
ztna.enabled | bool | false | Enable mTLS on the native TCP listener. Only takes effect whenenvironment is production; in development/test it is ignored and the listener stays cleartext. |
ztna.cert_path | String | "./certs/server.crt" | Server certificate for mTLS |
ztna.key_path | String | "./certs/server.key" | Server private key for mTLS |
ztna.client_ca_path | String | "./certs/ca.crt" | Client CA used to verify peer certificates |
security.auth_key.system_stream and security.auth_key.allow_local_auto_generation are currently parsed but not applied; the auth stream is hardcoded to auth_keys. mTLS covers the native TCP listener only — REST and WebSocket traffic remains HTTP.
Example Configuration File
[server]environment = "production"host = "0.0.0.0"db_port = 43121webui_port = 43120[storage]data_directory = "/var/lib/liven"max_segment_size_mb = 256sync_mode = "always"[limits]max_concurrent_streams = 64max_open_file_descriptors = 128max_index_ram_mb = 1024max_scan_results = 500000[security]mode = "auth_key"# master_key = "..." # prefer LIVEN_SECURITY_MASTER_KEY[security.ztna]enabled = false# cert_path = "./certs/server.crt"# key_path = "./certs/server.key"# client_ca_path = "./certs/ca.crt"
Configuration Profiles
Development
[server]environment = "development"host = "127.0.0.1"[security]mode = "none"[limits]max_concurrent_streams = 16max_open_file_descriptors = 32
Production
[server]environment = "production"host = "0.0.0.0"[security]mode = "auth_key"[security.ztna]enabled = truecert_path = "/etc/liven/certs/server.crt"key_path = "/etc/liven/certs/server.key"client_ca_path = "/etc/liven/certs/ca.crt"[limits]max_concurrent_streams = 64max_open_file_descriptors = 128max_index_ram_mb = 1024max_scan_results = 500000
Edge / Embedded
[limits]max_concurrent_streams = 8max_open_file_descriptors = 16max_index_ram_mb = 32max_scan_results = 10000
Index RAM Auto-Detection
When max_index_ram_mb is not explicitly set, Liven allocates 25% of detected host RAM, clamped to 32 MiB–4096 MiB. If detection fails, it falls back to 512 MiB. The 4 GiB value is an auto-detection ceiling, not a hard cap: an explicit larger value is accepted.
The limit is enforced against compound_key.len() + 128 bytes per live key: a 64-byte primary-index node and a 64-byte timestamp-index node. Allocator overhead and compaction scratch memory are still additional. Measured process RSS is roughly 157–192 bytes per key for the key lengths below.
| Budget | ~8-byte key | ~32-byte key |
|---|---|---|
| 16 MiB | ~107k keys | ~87k keys |
| 64 MiB | ~427k keys | ~349k keys |
| 256 MiB | ~1.7M keys | ~1.4M keys |
| 1 GiB | ~6.8M keys | ~5.6M keys |
| 4 GiB | ~27M keys | ~22M keys |
On Linux, detection reads /proc/meminfo (host-visible memory), not cgroup limits. In containers, set max_index_ram_mb explicitly.
At the accounting limit, new keys are rejected with IndexRamLimitExceeded. There is no eviction or spill. A database whose rebuilt index exceeds a too-small limit still opens by default: Liven loads it, logs the overage, and rejects only new keys (overwrites, deletes, and reads continue). --strict-recoveryrefuses to open instead.
Monitoring
status() returns connection/subscriber counters plus index usage: max_connections, broadcast_capacity, active_connections, broadcast_subscribers, index_ram_bytes, index_ram_limit_bytes, index_high_water_bytes, and index_high_water_reached. Use process RSS for total process memory.
Best Practices
- Set the index budget explicitly in containers — auto detection sees host RAM.
- Keep keys short — key length and stream name are part of every index entry.
- Use
[storage] max_segment_size_mb— the duplicate under[limits]is ignored. - Use environment variables for secrets — set
LIVEN_SECURITY_MASTER_KEYinstead of committing it. - Restart after config changes — configuration is read at startup.
limits.max_segment_size_mb, security.auth_key.system_stream, and security.auth_key.allow_local_auto_generation. The auth stream is hardcoded to auth_keys.