Deploy

Configuration

Nexir loads configuration at startup. Change TOML or environment variables, then restart the node; runtime CONFIG SET is not supported.

Loading and precedence

  1. Load a local .env file if present.
  2. Load config/default.toml if present relative to the working directory.
  3. Apply NEXIR__* environment variables.

Environment variables override TOML. Existing shell variables override values from .env. Nested names use double underscores:

NEXIR__SERVER__REDIS_BIND=127.0.0.1:16379
NEXIR__SERVER__TLS__CLIENT__MODE=require
NEXIR__STORAGE__PATH=/var/lib/nexir

Essential settings

TOML fieldEnvironment variableDefault
server.redis_bindNEXIR__SERVER__REDIS_BIND127.0.0.1:6379
server.grpc_bindNEXIR__SERVER__GRPC_BIND127.0.0.1:50051
server.default_read_modeNEXIR__SERVER__DEFAULT_READ_MODELINEARIZABLE
server.enable_admin_commandsNEXIR__SERVER__ENABLE_ADMIN_COMMANDSfalse
raft.node_idNEXIR__RAFT__NODE_ID1
storage.pathNEXIR__STORAGE__PATH./data/nexir
prometheus.bindNEXIR__PROMETHEUS__BIND127.0.0.1:9090
Identity is durableSet a unique node ID and storage path before first start. Never change the node ID for an existing data directory or let two processes share one storage path.

TLS settings

Both TLS surfaces default to disabled. require means mutual TLS and requires a certificate, matching private key, and CA bundle.

SurfaceFields under server.tlsEnvironment prefix
RESP clientsclient.mode, cert_file, key_file, ca_bundleNEXIR__SERVER__TLS__CLIENT__*
Raft peerscluster.mode, cert_file, key_file, ca_bundleNEXIR__SERVER__TLS__CLUSTER__*

Use separate client and cluster CA bundles. Startup rejects the same resolved CA file for both required surfaces. TLS files are read at startup; rotation requires restart.

Server resource defaults

FieldDefaultPurpose
max_connections10,000Concurrent RESP clients
max_inflight_commands_global100,000Unfinished commands across clients
max_inflight_commands_per_connection1,000Per-client command budget
max_inflight_bytes_global512 MiBGlobal in-flight request payload budget
max_inflight_bytes_per_connection64 MiBPer-client payload budget
max_client_buffer_bytes64 MiBUnread input per socket
max_buffered_client_bytes_global512 MiBBuffered input across clients
client_idle_timeout_secs300Idle RESP socket timeout
max_concurrent_reads_per_connection16Concurrent reads for one client
max_buffered_response_bytes_per_connection64 MiBQueued output per client
max_buffered_response_bytes_global512 MiBQueued output globally

Storage defaults

FieldDefaultNotes
block_cache_size_mb0 (derived)The node's one shared block cache: 50% of the process target
write_buffer_size_mb128State DB buffer; log DB uses twice this
max_write_buffers4Storage-engine write buffers
enable_bloom_filterstruePoint lookup filters
read_io_threads0 (auto)Available cores clamped to 4–64
write_io_threads2Blocking write workers
cleanup_io_threads1Background cleanup worker
max_read_reply_bytes0 → 64 MiBResolves to per-client response limit
max_reader_pin_ms300,000Five-minute maximum read lifetime
max_snapshot_files10,000Accepted snapshot file count
max_snapshot_size_bytes64 GiBSnapshot size cap; must match across nodes
max_archive_bytes64 GiBSnapshot transfer cap; must match across nodes
max_retained_snapshot_bytes256 GiBRetained snapshot budget
min_free_disk_bytes1 GiBFree-space reserve: snapshot receives are refused and snapshot builds deferred below it

Memory defaults

Each node plans its memory once at startup from the smaller of its host memory and any container (cgroup) limit. These are targets and capacities, not hard ceilings on resident memory. Every field is under [memory]; 0 means derived.

FieldDefaultNotes
process_target_bytes0 (derived)Process target P: 75% of available memory. New writes are refused with -TRYAGAIN while resident memory is at 90% of it
state_memtable_bytes / log_memtable_bytes0 (derived)Write-buffer capacity for the state database and the Raft log
reserved_headroom_bytes0 (derived)What remains of P; client replies must fit in half of it

With default settings a host of about 6 GB or more starts; a 4 GiB node is refused at startup until connection, in-flight command or response limits are lowered. See the configuration reference.

Raft defaults

FieldDefault
snapshot_policy_logs100,000
max_pending_write_tasks10,000
max_pending_write_bytes256 MiB
max_inflight_read_barriers10
max_queued_linearizable_reads100,000
membership_preflight_timeout_ms3,000
membership_change_timeout_ms30,000
add_learner_catchup_timeout_ms300,000
transfer_leader_timeout_ms10,000
heartbeat_interval_ms1,000
election_timeout_min_ms / max_ms3,000 / 5,000
log_retention_budget_bytes32 GiB
log_retention_retry_spacing_secs15
log_retention_episode_max_secs / cooldown_secs1,800 / 1,800

The four log_retention_* settings bound follower catch-up log retention, which is always on. Every value must be positive. The defaults are sized for nodes with at least 200 GiB of disk; lower the budget on smaller disks. A budget above half of the data filesystem logs a startup warning.

Logging

RUST_LOG controls tracing output and defaults to info. Use warn for quieter operation or debug temporarily while diagnosing a problem.

Startup validation

Nexir rejects a memory plan that cannot fit, invalid addresses and modes, zero required limits, inconsistent global/per-connection budgets, request budgets below 60 MiB, invalid I/O queue sizes, unsafe snapshot limits, invalid Raft timing relationships, and missing or mismatched TLS files. It exits with a useful startup error rather than silently altering invalid settings.