How CortexDB resolves configuration: the cortex.toml file, environment variables, CLI flags, precedence rules, and reload semantics.

Configuration Foundations

This page covers the mechanics — where files live, what overrides what, and what happens on reload. For tuning advice, see the per-subsystem pages.

Resolution order

When the cortexdb binary starts, configuration is resolved in this order. Each step overrides the previous.

  1. Compiled defaults. Defined in cortex-config/src/lib.rs as default_*() functions. These are what you get with zero config.
  2. <data_dir>/cortex.toml. Loaded by LiveConfig::from_file() at startup. Missing fields fall back to compiled defaults; missing file falls back to all defaults with a warning logged.
  3. Environment variables. Read inline by each subsystem on first use. Most overrides are honored at startup; a handful (recall-tuning knobs) are read per-request.
  4. CLI flags. Used only for cluster topology (--node-id, --rpc-addr, --gossip-addr, --seed-nodes, --rf, --port, --data-dir, --peers). There is no CLI flag that duplicates a TOML field or env var.

The data_dir itself is resolved from the second positional CLI argument (or --data-dir= in cluster mode), defaulting to cortexdb_data in single-node mode and cortexdb_data_{node_id} in cluster mode. Once data_dir is known, the config file is always read from <data_dir>/cortex.toml.

The cortex.toml file

Location

<data_dir>/cortex.toml

This means changing your data directory also moves the config file. If you point at a fresh data_dir, you'll get pristine defaults — useful for repeatable benchmarks, surprising for operators.

Schema

The full schema is in cortex-config/src/lib.rs. The 14 top-level sections are:

SectionPurpose
[cluster]Node identity, peer set, replication factor, vnodes
[storage]Data path, WAL sync mode, disk watermarks
[engine]RocksDB cache, HNSW shape, vector dims, quantization
[network]API / gossip / gRPC ports, request timeouts
[llm]Default LLM provider, model, fallback chain
[governance]Retention, PII handling, audit logging
[scheduler]Background job intervals (compaction / methylation / drain)
[blob_store]Local / S3 / GCS / Azure blob backend + KMS
[content_processors]Image / audio / video / document / sensor handlers
[security]Encryption, TLS/mTLS, RBAC, rate limits, breach detection, field masking
[compliance]Data residency, consent, classification, DSAR, SIEM, cross-agent
[deployment]Profile preset + per-feature gate overrides

Every field uses serde(default = "..."), so partial files are valid — you only need to specify what you want to change. This is the file used to produce 93.8% on LongMemEval-S:

# cortexdb_data_server/cortex.toml — the benchmark override file
[cluster]
node_id = 1

[storage]
[engine]
[network]
[llm]
[governance]

[scheduler]
enabled = false

Empty sections mean "use all defaults for this section." The only non-default field is scheduler.enabled = false — required because background compaction pollutes the vector index over long bench runs.

Validation

LiveConfig::from_file() returns a ConfigError::ValidationError if a field is out of range. Examples that will refuse to start:

  • engine.vector_dimensions not in {256, 384, 512, 768, 1024, 1536, 3072}
  • engine.hnsw_m outside [4, 64]
  • storage.max_disk_usage_percent > 100
  • cluster.replication_factor == 0
  • scheduler.compaction_interval_secs < 30

A bad config file fails fast at startup rather than silently using defaults. Watch the logs on first boot.

Reload semantics

cortex.toml is read once at startup. There is no SIGHUP reload. To change a TOML field you must restart the binary. This is intentional — most fields (vector_dimensions, data_path, cluster topology) cannot be safely changed at runtime.

For tunables you do want to change without restart, use the environment-variable overrides documented in Recall Tuning. Those are read on the request path.

Environment variables

Roughly 100 variables exist, grouped by prefix. The high-level convention:

PrefixSubsystemExamples
CORTEX_LOG_*LoggingCORTEX_LOG_FORMAT=json
CORTEX_EMBEDDING_*EmbeddingsCORTEX_EMBEDDING_MODEL, CORTEX_EMBEDDING_DIMS
CORTEX_LLM_*Entity-extraction LLMCORTEX_LLM_MODEL=gpt-4o-mini
CORTEX_ANSWER_*Answer-generation LLMCORTEX_ANSWER_MODEL=claude-opus-4-6
CORTEX_VERIFIER_*Optional answer verifierCORTEX_VERIFIER_MODEL=gpt-4.1
CORTEX_ENRICHMENT_*Async KG enrichment LLMCORTEX_ENRICHMENT_MODEL= (off by default)
CORTEX_BLOB_*Blob storage backendCORTEX_BLOB_PROVIDER=s3
CORTEX_IMAGE_*, CORTEX_AUDIO_*, etc.Content modality processorsCORTEX_AUDIO_MODEL=whisper-1
CORTEX_RERANKER_*Cross-encoder rerankerCORTEX_RERANKER_PROVIDER=cohere
CORTEX_*_DISABLEKill switchesCORTEX_SCHEDULER_DISABLE=1
CORTEX_METHYLATION_*, CORTEX_CONSOLIDATION_*Memory evolution thresholdsCORTEX_METHYLATION_MIN_ACCESS=10
CORTEX_GRAPH_RETRIEVAL_*, CORTEX_MULTIHOP_*, CORTEX_HYDE_*Recall-strategy tuningCORTEX_GRAPH_RETRIEVAL_TOP_K=40
CORTEX_SYNC_*Synchronous-pipeline kill switchesCORTEX_SYNC_FACT_EXTRACT_DISABLE=1
CORTEX_MS_*Multi-session executor flagsCORTEX_MS_EVIDENCE_PACK_DISABLE=1

A handful of env vars use the underlying ecosystem's name rather than CORTEX_*:

  • OPENAI_API_KEY — used as the embedding key when no provider-specific key is set
  • ANTHROPIC_API_KEY — fallback for CORTEX_ANSWER_API_KEY when provider is anthropic
  • COHERE_API_KEY — used when CORTEX_EMBEDDING_PROVIDER=cohere
  • LLM_API_KEY — generic fallback when no provider-specific key is set
  • RUST_LOG — picked up by tracing_subscriber (overrides the default cortexdb=info,... filter)

Boolean conventions

Boolean env vars accept 1 / 0, true / false (case-insensitive). Empty or unset means default. Most boolean knobs are kill switches — they start in the "feature on" state and you set =1 to disable. Examples: CORTEX_LLM_DISABLE, CORTEX_SCHEDULER_DISABLE, CORTEX_GRAPH_RETRIEVAL_DISABLE, CORTEX_MS_EVIDENCE_PACK_DISABLE.

The exceptions — features that start off and you opt into — include CORTEX_AUTO_ROUTE, CORTEX_COMPOSITIONAL_ENABLE, CORTEX_ENTITY_VECTOR_SEED_ENABLE, CORTEX_ENUMERATE_COUNT_ENABLE. The _ENABLE suffix is the giveaway.

CLI flags

Only 10 flags exist, all about cluster topology. Single-node operators don't need any of them — cortexdb with no arguments binds the v1 API on port 3141 and writes to ./cortexdb_data.

Single-node mode

cortexdb [PORT] [DATA_DIR]

Two positional args. Both optional.

# All defaults: API on 3141, data in ./cortexdb_data
cortexdb

# Custom port, custom data dir
cortexdb 4000 /var/lib/cortexdb

In single-node mode, the legacy API surface (kept for back-compat with bench scripts) binds to 127.0.0.1:<PORT+1> — by default 127.0.0.1:3142. Override with CORTEX_LEGACY_API_ADDR if you need to expose it externally.

Cluster mode

Trigger by passing --node-id, --rpc-addr, and --gossip-addr together. All other flags become available:

cortexdb \
  --node-id=1 \
  --rpc-addr=10.0.0.1:7100 \
  --gossip-addr=10.0.0.1:7000 \
  --seed-nodes=10.0.0.1:7000,10.0.0.2:7000,10.0.0.3:7000 \
  --rf=3 \
  --port=3141 \
  --data-dir=/data/cortex/node1
FlagRequired?DefaultWhat it does
--node-id=NYes (cluster)Unique u64 for this node. Must be stable across restarts.
--rpc-addr=HOST:PORTYes (cluster)Internal RPC bind address for inter-node calls.
--gossip-addr=HOST:PORTYes (cluster)UDP gossip / membership bind address.
--seed-nodes=A,B,CYes (cluster)Comma-separated peers to contact for cluster join.
--peers=ID:HOST:PORT,...NoAlternative explicit peer list (with ids).
--rf=NNo3Replication factor — number of copies per partition.
--port=PORTNo3141V1 API bind port (0.0.0.0:PORT).
--data-dir=DIRNocortexdb_data_{node_id}RocksDB + cortex.toml location.

All four required flags must be present together to trigger cluster mode. If any one is missing, the binary silently falls back to single-node mode and you get a one-machine cluster that ignores the other flags. Watch the startup logs for "Cluster mode" vs "Single-node mode" to confirm.

See Storage & Cluster for the full cluster operations guide.

Inspecting what's actually loaded

On startup, CortexDB logs the resolved scheduler config:

scheduler configuration loaded
  enabled=true
  compaction_interval_secs=300
  methylation_interval_secs=600
  cognitive_persist_interval_secs=60
  feedback_weight_interval_secs=120

For everything else, use the health and config endpoints:

# Basic health + version
curl http://localhost:3141/v1/admin/health

# Full effective config (admin scope required)
curl http://localhost:3141/v1/admin/config \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Cortex-Actor: $ACTOR"

The /v1/admin/config response shows the resolved values after defaults + file + env are merged — useful for confirming an env var actually took effect rather than being silently ignored.

Next steps