Configuration reference
Every server option is a command-line flag and an environment variable. The env var is the flag in upper snake case with a CELERIANT_ prefix: --data-root is CELERIANT_DATA_ROOT, --num-shards is CELERIANT_NUM_SHARDS. The server also loads a .env file from its working directory if one exists. At boot it logs every setting that differs from the default, so the log shows the effective config.
Switches such as --standalone take no value on the command line. Use the env form (CELERIANT_STANDALONE=true) to set them from a container spec.
Settings you cannot change later
The first boot writes server_meta.toml into --data-root. Every later boot compares the current settings with it and refuses to start on any mismatch. Changing one of these means a new data directory.
--num-shards--routing-rule--timestamp-precision--timestamp-epoch-offset-secs--reserve-coordinator-shard--wal-compression-level--wal-dictionary-name
--num-shards defaults to the CPU count of the machine it first ran on. Move that data directory to a host with a different core count and the node will not start. Set it explicitly.
Node and network
| Flag | Default | Notes |
|---|---|---|
--data-root | data | Data directory. Must enforce O_DIRECT; the server checks at boot and exits if writes silently fall back to buffered I/O. |
--listen-address | 0.0.0.0 | Bind address for the client and replication ports. |
--client-port | 10000 | Client connections. |
--replication-port | 10001 | Leader-to-follower replication and heartbeats. |
--advertised-client-address | {listen-address}:{client-port} | Address written to S3 membership and returned in NotLeader errors. Set it when clients connect through a load balancer or proxy. |
--advertised-replication-address | {listen-address}:{replication-port} | Replication address written to S3 membership. The peer dials this. |
--standalone | off | Single node. No replication, no S3 election. |
--log-level | info | trace, debug, info, warn, error. A RUST_LOG env var overrides it. |
The advertised defaults inherit --listen-address. With the default 0.0.0.0, the peer and clients get an address they cannot dial, so a cluster node needs both advertised addresses set.
Sharding and data layout
All immutable after first boot.
| Flag | Default | Notes |
|---|---|---|
--num-shards | CPU count | One shard per core. |
--routing-rule | aggregate_id | org_id, aggregate_type_id, or aggregate_id. Decides which aggregates share a shard and so which can be co-committed. |
--reserve-coordinator-shard | false | Shard 0 handles only cluster coordination (heartbeat, schema); client data routes to shards 1 and up. Needs at least 2 shards. |
--timestamp-precision | milliseconds | Precision of the server-assigned timestamp: milliseconds, microseconds, or nanoseconds. |
--timestamp-epoch-offset-secs | 0 | Custom epoch, as seconds from the Unix epoch. Shifts the server-assigned timestamp, not event timestamps a client sets. |
--wal-compression-level | 3 | zstd level for the WAL. |
--wal-dictionary-name | json-web-events-v1 | Name of the zstd dictionary, not a path. The built-in one is written to dictionary.zstd_dict on first boot. |
Cluster and failover
| Flag | Default | Notes |
|---|---|---|
--heartbeat-interval-ms | 500 | Leader heartbeat cadence. |
--heartbeat-timeout-ms | = interval | Timeout for one heartbeat connect and request. Keep it below --heartbeat-lease-duration-ms. |
--heartbeat-hard-timeout-multiplier | 4 | Hard cap on a heartbeat, as a multiple of the timeout. Catches kTLS sends blocked in the kernel that ignore the soft timeout. |
--heartbeat-lease-duration-ms | 1500 | Silence after which the follower treats the leader's lease as expired and challenges. |
--heartbeat-starve-threshold-ms | 500 | While a heartbeat has been in flight longer than this, reject writes (FollowerHeartbeatStarved) so the NIC has room for the ack. Skipped when the follower is unreachable. 0 disables. |
--s3-lease-duration-ms | 30000 | TTL of the lease object in S3, independent of heartbeat timing. See leader election. |
--max-clock-drift-ms | 500 | Drift allowance added to lease checks. The leader fences itself this much before expiry. |
--internode-connection-timeout-ms | 1000 | Inter-node TCP connect timeout. |
--internode-request-timeout-ms | 2000 | Bounds one inter-node round trip. Raise it on high-latency links. |
--internode-max-request-size | 64 MiB | Cap on one replication batch. In-flight write bytes reaching it trigger write backpressure. |
Write pipeline
Wider windows batch more writes per fsync or send. That buys throughput and costs per-write latency.
| Flag | Default | Notes |
|---|---|---|
--fsync-delay-us | 4000 | Window in which writes are coalesced into one fsync. |
--replication-delay-us | 17000 | Same, for the replication send to the follower. |
--s3-replication-delay-us | 500000 | Same, while replicating through S3 fallback. Longer, to put more entries in each upload. |
--replication-rollback-cooldown-us | 500000 | After a replication rollback, reject writes with ReplicationBackpressure for this long so the queue drains. |
--s3-max-concurrent-fallback-uploads | 128 | Parallel S3 fallback uploads across all shards. Sized for AWS; lower it for MinIO or a LAN store where saturation can starve lease renewal. |
S3
Required unless --standalone. A clustered node without S3 retries its membership registration every 2 s and never finishes booting.
| Flag | Default | Notes |
|---|---|---|
--s3-enabled | off | Turns S3 on. Needs --s3-region and --s3-bucket. |
--s3-region / --s3-bucket | none | The store must support conditional writes (If-Match / If-None-Match); election depends on them. |
--s3-access-key-id / --s3-secret-access-key | none | Static credentials. Leave both unset to use the EC2 instance profile. The standard AWS_* env vars are not read. |
--s3-subfolder | none | One-level prefix, so several clusters can share a bucket. |
--s3-endpoint-override | none | For MinIO and other S3-compatible stores. |
--s3-retry-max-duration-secs | unset | Caps how long a lease or election call retries an unreachable S3 (backoff from 1 s, doubling to 30 s). Unset retries forever. |
--s3-allow-http / --s3-skip-signature | off | Local testing only. |
The server checks S3 reachability at boot and exits if the endpoint, credentials, or bucket are wrong.
TLS and authentication
| Flag | Default | Notes |
|---|---|---|
--tls-mode | disabled | disabled (plaintext only) or strict (TLS only). Needs kernel kTLS. See TLS and mTLS. |
--tls-ca-cert / --tls-node-cert / --tls-node-key | none | Trust root and node identity, PEM. All three required under strict. |
--tls-intracluster-ca-cert | none | Separate CA for the replication port. When set, the client port trusts only --tls-ca-cert. |
--tls-client-cert / --tls-client-key | none | Certificate the client port presents instead of the node cert. |
--tls-client-auth | require | require (mTLS), optional, or none. |
--tls-cert-reload-interval-secs | 0 | How often to re-read cert files and hot-reload them. 0 disables. |
--require-client-identity | off | Clients must send the identity handshake first. |
--insecure-allow-plaintext-auth | off | Allow API keys or client identity without TLS. Development only. |
API keys are not a flag. The server reads them from <data-root>/api_keys.toml; celeriant keys generate --data-root <dir> creates it. If API keys or --require-client-identity are on and TLS is off, the server refuses to start unless --insecure-allow-plaintext-auth is set.
Storage, compaction, and memory
| Flag | Default | Notes |
|---|---|---|
--shard-log-preallocate-bytes | 1 GiB | Size of each WAL file. |
--compaction-check-interval-secs | 7200 | How often to scan for compactable segments. |
--compaction-min-reclaimable-ratio | 0.20 | Share of reclaimable bytes a segment needs before it is compacted. |
--compaction-temp-dir | {shard_dir}/.compaction_tmp/ | Must be on the same filesystem as --data-root. Checked at boot. |
--cache-warmup-max-secs | unset | Time limit for cache warmup on shard open. Unset means no limit. |
--memory-consumption-percent | 80 | Share of detected memory (the cgroup limit if lower) given to caches. 1 to 95. |
--memory-budget-bytes | unset | Explicit total cache budget. Overrides detection. |
--recent-write-cache-ratio | 0.73 | Share of each shard's budget for the recent-write cache. |
--negative-lookup-cache-bytes | 2 MiB | Per-shard budget for the idempotency-scan blooms. Eviction costs a rebuild scan, never correctness. |
Request limits
| Flag | Default | Notes |
|---|---|---|
--max-request-size | 16 MiB | Per client request, compressed and uncompressed. |
--max-response-size | 64 MiB | Per response. |
--max-requested-latency-ms | 2000 | Upper bound on the latency a watch may request. |
--max-watch-subscribers | 16384 | Watch subscriptions per shard. Past it, a watch gets error 8005. |
--max-schema-size-bytes | 16384 | One schema definition. |
--list-page-size | 2000 | Entities per list page. |
--list-max-duration-ms | 2000 | Time a list may spend scanning the WAL. |
--list-max-concurrent | 16 | Concurrent list operations per shard. |
--read-max-concurrent | 64 | Concurrent backward metablock scans per shard. |
--client-connection-timeout-ms | 30000 | How long a client has to read server messages before it is dropped. |
--handshake-concurrency | 8 | TLS handshakes in flight per shard, per port. |
Observability
| Flag | Default | Notes |
|---|---|---|
--metrics-enabled | on | Serves /metrics and /health. The flag cannot switch it off; set CELERIANT_METRICS_ENABLED=false. |
--metrics-port | 9090 | See Monitoring. |
Low-level tuning
Leave these alone unless a profile says otherwise.
| Flag | Default | Notes |
|---|---|---|
--mesh-channel-size | 8192 | Inter-shard channel capacity. |
--max-open-files | 1000 | Open files per shard. |
--read-max-chunk-size / --write-max-chunk-size | 32768 | Disk read and write chunk size in bytes. |
--chain-read-window-bytes | 1024 | Per-hop read window when walking an aggregate's backlink chain for old versions. Raise toward the read chunk size for shards with few, long aggregates. |
--preempt-timer-us | 250 | How long a task runs before the scheduler and reactor get the CPU. 50 to 100000. |
--wal-join-data-meta-writes | true | Submit a sync's datablock and metablock writes together. Takes an explicit true or false. |
Tuning notes
- S3 fallback costs latency. While the follower is unreachable, writes replicate through S3 and wait on
--s3-replication-delay-us(500 ms by default) to fill each upload. Fewer PUTs, slower acks. A follower down for hours means hours of that. - NTP is required. The server warns at boot if the kernel clock is not NTP-disciplined.
--max-clock-drift-msis slack for lease checks, not a substitute for sync.