Configuration

AionDB can be configured through CLI flags and environment variables. CLI flags should be used for local clarity; environment variables are useful for scripts, benchmark harnesses, and deployments.

CLI flags

aiondb --help
aiondb --version
aiondb --ephemeral
aiondb --data-dir ./data/aiondb
aiondb --storage-backend durable

Storage backend values:

For v0.1, use --ephemeral for demos and durable for persistent local evaluation unless you are testing a specific backend. The storage v1 compatibility promise covers durable SQL table/WAL/index files; lsm remains an experimental backend format.

Configuration precedence

Prefer CLI flags for values a human should see immediately, such as --ephemeral or --data-dir. Prefer environment variables for scripts and benchmark harnesses where the same command needs to run across machines.

When documenting a benchmark or bug, include both:

That prevents hidden environment state from changing the result.

Common environment variables

VariablePurpose
AIONDB_PGWIRE_LISTEN_ADDRPostgreSQL wire listen address. Default: 127.0.0.1:5432.
AIONDB_STORAGE_BACKENDStorage backend. Same values as --storage-backend.
AIONDB_STORAGE_DATA_DIRPersistent storage directory.
AIONDB_IN_MEMORYRun with in-memory storage when set to true.
AIONDB_OBSERVABILITY_BINDObservability HTTP bind address. Default: 127.0.0.1.
AIONDB_OBSERVABILITY_PORTObservability HTTP port. Default: 9187.
AIONDB_PGWIRE_TLS_MODEdisable, prefer, or require.
AIONDB_BOOTSTRAP_USERDevelopment bootstrap role.
AIONDB_BOOTSTRAP_PASSWORDDevelopment bootstrap password.
AIONDB_ALLOW_UNENCRYPTED_STORAGEDevelopment override for persistent storage on an unencrypted filesystem.

The systemd packaging profile includes packaging/systemd/aiondb.env.example. Copy it to /etc/aiondb/aiondb.env, restrict permissions, and replace all commented placeholders before enabling the service. The example keeps the bootstrap user disabled, requires TLS, and leaves the unencrypted-storage override commented so production-style evaluations do not inherit tutorial defaults.

Subsystem variables

Variables that belong to a single subsystem are grouped by prefix. The loader rejects unknown AIONDB_* names when AIONDB_CONFIG_STRICT=true.

Security

AIONDB_SECURITY_PROFILE=development|staging|production
AIONDB_SECURITY_ALLOW_ANONYMOUS_LOCAL=false
AIONDB_SECURITY_ALLOW_EPHEMERAL_USERS=false
AIONDB_SECURITY_REQUIRE_TLS_FOR_PASSWORD=true
AIONDB_SECURITY_PASSWORD_MIN_LENGTH=12
AIONDB_SECURITY_PASSWORD_REQUIRE_LOWERCASE=true
AIONDB_SECURITY_PASSWORD_REQUIRE_UPPERCASE=true
AIONDB_SECURITY_PASSWORD_REQUIRE_DIGIT=true
AIONDB_SECURITY_PASSWORD_REQUIRE_SYMBOL=true
AIONDB_SECURITY_REJECT_ROLE_NAME_AS_PASSWORD=true
AIONDB_SECURITY_MAX_AUTH_FAILURES=5
AIONDB_SECURITY_AUTH_LOCKOUT_WINDOW_MS=600000
AIONDB_SECURITY_DURABLE_AUTH_LOCKOUT=false
AIONDB_SECURITY_AUTH_LOCKOUT_STATE_PATH=/var/lib/aiondb/auth-lockout.state
AIONDB_SECURITY_DURABLE_AUTH_AUDIT=false
AIONDB_SECURITY_AUTH_AUDIT_LOG_PATH=/var/log/aiondb/auth-audit.log
AIONDB_SECURITY_AUTH_AUDIT_MAX_FILE_SIZE_BYTES=10485760
AIONDB_SECURITY_AUTH_AUDIT_MAX_ROTATED_FILES=5
AIONDB_SECURITY_DDL_AUDIT_ENABLED=false
AIONDB_SECURITY_MAX_CONCURRENT_SESSIONS_PER_ROLE=100
AIONDB_SECURITY_MAX_SESSION_IDLE_TIMEOUT_MS=0
AIONDB_SECURITY_MAX_SESSION_LIFETIME_MS=0
AIONDB_SECURITY_MAX_TRANSACTION_IDLE_TIMEOUT_MS=0

pgwire

AIONDB_PGWIRE_LISTEN_ADDR=127.0.0.1:5432
AIONDB_PGWIRE_TLS_MODE=disable|prefer|require
AIONDB_PGWIRE_TLS_CERT_PATH=/path/server.crt
AIONDB_PGWIRE_TLS_KEY_PATH=/path/server.key
AIONDB_PGWIRE_TLS_CLIENT_CA_PATH=/path/client-ca.crt
AIONDB_PGWIRE_STARTUP_TIMEOUT_MS=10000
AIONDB_PGWIRE_IDLE_TIMEOUT_MS=0
AIONDB_PGWIRE_AUTH_FAILURE_BACKOFF_MS=500
AIONDB_PGWIRE_MAX_CONNECTIONS=200
AIONDB_PGWIRE_MAX_CONNECTIONS_PER_IP=50
AIONDB_PGWIRE_COPY_IN_MAX_BUFFER=8388608
AIONDB_PGWIRE_COPY_IN_TOTAL_TIMEOUT_MS=60000

Engine pool

AIONDB_ENGINE_POOL_WORKER_THREADS=4
AIONDB_ENGINE_POOL_QUEUE_DEPTH=64
AIONDB_ENGINE_DISABLE_PARSED_SQL_FINGERPRINT_CACHE=false

Replication

AIONDB_REPLICATION_ROLE=primary|replica
AIONDB_REPLICATION_PRIMARY_CONNINFO="host=primary.example.com port=5432 user=replicator application_name=node-b"
AIONDB_REPLICATION_MAX_WAL_SENDERS=8
AIONDB_REPLICATION_FACTOR=1
AIONDB_REPLICATION_WRITE_CONCERN=local|majority|all|factor:N
AIONDB_REPLICATION_SYNCHRONOUS_COMMIT=true
AIONDB_REPLICATION_SYNC_COMMIT_TIMEOUT_MS=10000
AIONDB_REPLICATION_STATUS_INTERVAL_MS=1000
AIONDB_REPLICATION_WAL_KEEP_SEGMENTS=16
AIONDB_REPLICATION_WAL_COMPRESSION=none|lz4|zstd
AIONDB_REPLICATION_WAL_LSN_MODE=logical|byte_offset
AIONDB_REPLICATION_PROMOTE_ON_START=false

For distributed replica repair, set application_name in AIONDB_REPLICATION_PRIMARY_CONNINFO to the same value as the node's distributed NodeId. The primary records that name in replication progress, so staged learners can be promoted only after the matching replica reports apply_lsn catch-up.

AIONDB_REPLICATION_WRITE_CONCERN also accepts the legacy aliases async for local and sync for all. For factor:N, N is a replica-ack count, must be at least 1, and must not exceed AIONDB_REPLICATION_FACTOR - 1. AIONDB_REPLICATION_SYNCHRONOUS_COMMIT=true is a legacy compatibility flag; it upgrades the default write concern to majority only when AIONDB_REPLICATION_WRITE_CONCERN is not set.

The replica client does not negotiate TLS yet. sslmode=require, sslmode=verify-ca, and sslmode=verify-full are rejected instead of falling back to plaintext.

AIONDB_REPLICATION_PRIMARY_CONNINFO accepts libpq-style quoted values for spaces and rejects embedded NUL bytes before building startup or password frames.

High availability

AIONDB_HA_ENABLED=false
AIONDB_HA_NODE_ID=1
AIONDB_HA_PORT=7600
AIONDB_HA_CLUSTER_NODES="host1:7600,host2:7600"
AIONDB_HA_AUTH_TOKEN=<shared-secret>
AIONDB_HA_HEALTH_CHECK_INTERVAL_MS=3000
AIONDB_HA_HEALTH_CHECK_TIMEOUT_MS=10000
AIONDB_HA_ELECTION_TIMEOUT_MS=30000
AIONDB_HA_MAX_FAILOVER_LAG=1000
AIONDB_HA_FENCING_TOKEN_PATH=/var/lib/aiondb/fencing

AIONDB_HA_HEALTH_CHECK_TIMEOUT_MS must be greater than AIONDB_HA_HEALTH_CHECK_INTERVAL_MS. AIONDB_HA_ELECTION_TIMEOUT_MS must be greater than AIONDB_HA_HEALTH_CHECK_TIMEOUT_MS. The loader rejects configurations that violate these ordering constraints.

AIONDB_HA_NODE_ID is one-based: 1 refers to the first address in AIONDB_HA_CLUSTER_NODES, 2 to the second, and so on.

Sharding

AIONDB_SHARDING_ENABLED=false
AIONDB_SHARDING_DEFAULT_SHARD_COUNT=16
AIONDB_SHARDING_VIRTUAL_NODES_PER_SHARD=128
AIONDB_SHARDING_REPLICATION_FACTOR=1
AIONDB_SHARDING_AUTO_REBALANCE=false
AIONDB_SHARDING_MAX_LEARNERS_PER_SHARD=1
AIONDB_SHARDING_MAX_LEARNERS_PER_NODE=64
AIONDB_SHARDING_LEADERSHIP_MAX_TRANSFERS_PER_MAINTENANCE=16
AIONDB_SHARDING_LEADERSHIP_MIN_LOAD_DELTA=1
AIONDB_SHARDING_NODE_ATTRIBUTES="local:region=eu-west;zone=az-a,node-b:region=eu-north;zone=az-b"
AIONDB_SHARDING_PLACEMENT_REQUIRED_ATTRIBUTES="disk=ssd"
AIONDB_SHARDING_LEASE_PREFERENCE_ATTRIBUTES="region=eu-west"
AIONDB_SHARDING_PLACEMENT_SPREAD_ATTRIBUTES="region,zone"

Placement policy is applied to initial shard placement and configured automatic repair. Required attributes filter candidate voters. Lease preferences choose the initial leader/leaseholder when matching candidates exist. Spread attributes try to keep voting replicas apart across failure domains such as region and zone. Leadership balancing is bounded per maintenance pass with AIONDB_SHARDING_LEADERSHIP_MAX_TRANSFERS_PER_MAINTENANCE, and live-leader balancing only moves leaders when the source is at least AIONDB_SHARDING_LEADERSHIP_MIN_LOAD_DELTA hotter than the target.

Distributed execution

AIONDB_DISTRIBUTED_FRAGMENT_TRANSPORT_PORT=7700
AIONDB_DISTRIBUTED_FRAGMENT_TRANSPORT_FAIL_FAST=false
AIONDB_DISTRIBUTED_INTER_NODE_AUTH_TOKEN=<shared-secret>
AIONDB_DISTRIBUTED_REMOTE_NODES="node-a=host-a:7700,node-b=host-b:7700"
AIONDB_DISTRIBUTED_REMOTE_SNAPSHOT_MODE=latest_visible|coordinator
AIONDB_DISTRIBUTED_REMOTE_CONNECT_TIMEOUT_MS=5000
AIONDB_DISTRIBUTED_REMOTE_RETRY_BACKOFF_MS=250
AIONDB_DISTRIBUTED_REMOTE_MAX_RETRIES=3
AIONDB_DISTRIBUTED_REMOTE_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
AIONDB_DISTRIBUTED_REMOTE_CIRCUIT_BREAKER_RESET_TIMEOUT_MS=30000
AIONDB_DISTRIBUTED_ALLOW_UNREGISTERED_LOOPBACK_NODES=false
AIONDB_DISTRIBUTED_LOOPBACK_NODES="node-test"
AIONDB_DISTRIBUTED_REQUIRE_TLS=true
AIONDB_DISTRIBUTED_TLS_CERT_PATH=/path/node.crt
AIONDB_DISTRIBUTED_TLS_KEY_PATH=/path/node.key
AIONDB_DISTRIBUTED_TLS_CA_CERT_PATH=/path/cluster-ca.crt

WAL integrity

AIONDB_WAL_LOCAL_HMAC_KEY=<32-byte-hex>
AIONDB_WAL_ARCHIVE_HMAC_KEY=<32-byte-hex>

When set, the WAL writer persists a .auth HMAC sidecar next to every active segment and recovery refuses records whose bytes were modified offline. The key must live outside the data directory.

Per-session limits

AIONDB_LIMITS_STATEMENT_TIMEOUT_MS=30000
AIONDB_LIMITS_LOCK_TIMEOUT_MS=1000
AIONDB_LIMITS_MAX_RESULT_ROWS=10000
AIONDB_LIMITS_MAX_RESULT_BYTES=8388608
AIONDB_LIMITS_MAX_MEMORY_BYTES=67108864
AIONDB_LIMITS_MAX_TEMP_BYTES=268435456
AIONDB_LIMITS_MAX_PARALLEL_WORKERS_PER_QUERY=1
AIONDB_LIMITS_MAX_PORTALS=64
AIONDB_LIMITS_MAX_PREPARED_STATEMENTS=128
AIONDB_LIMITS_MAX_RECURSIVE_ITERATIONS=10000
AIONDB_LIMITS_MAX_RECURSIVE_ROWS=1000000

Operational toggles

AIONDB_CONFIG_STRICT=true
AIONDB_ALLOW_PLAINTEXT_PUBLIC=false
AIONDB_ALLOW_PUBLIC_OBSERVABILITY=false
AIONDB_DISABLE_MEMORY_GUARD=false
AIONDB_OBSERVABILITY_FAIL_FAST=false

AIONDB_CONFIG_STRICT=true makes the loader reject unknown AIONDB_* variables. The ALLOW_PUBLIC_* toggles must remain false unless the deployment owner has actively decided to expose the surface; they exist so that an accidental non-loopback bind fails closed instead of silently going public.

Limits

AionDB includes explicit limits for result size, memory, temporary data, recursive execution, portals, prepared statements, and statement timeout. The defaults are conservative because v0.1 is an alpha.

Common limit variables:

AIONDB_LIMITS_STATEMENT_TIMEOUT_MS=30000
AIONDB_LIMITS_MAX_RESULT_ROWS=10000
AIONDB_LIMITS_MAX_RESULT_BYTES=8388608
AIONDB_LIMITS_MAX_MEMORY_BYTES=67108864
AIONDB_LIMITS_MAX_TEMP_BYTES=268435456
AIONDB_LIMITS_MAX_PARALLEL_WORKERS_PER_QUERY=1

Benchmark scripts may override these values so benchmark runs are not accidentally capped by small development defaults.

Example local profiles

Ephemeral development:

AIONDB_BOOTSTRAP_USER=dev \
AIONDB_BOOTSTRAP_PASSWORD='DevPassword42!' \
aiondb --ephemeral

Persistent local evaluation:

AIONDB_BOOTSTRAP_USER=dev \
AIONDB_BOOTSTRAP_PASSWORD='DevPassword42!' \
AIONDB_ALLOW_UNENCRYPTED_STORAGE=true \
aiondb --data-dir ./data/aiondb

Custom pgwire port:

AIONDB_PGWIRE_LISTEN_ADDR=127.0.0.1:15432 \
aiondb --ephemeral

WAL durability

The durable backend defaults to fsync on commit. Development and benchmark runs may relax this with:

AIONDB_STORAGE_DURABLE_WAL_COMMIT_POLICY=always
AIONDB_STORAGE_DURABLE_WAL_COMMIT_POLICY=every:10
AIONDB_STORAGE_DURABLE_WAL_COMMIT_POLICY=never

Use always for durability-sensitive evaluation. Non-always policies are for controlled benchmarks and development only.

Configuration hygiene

Do not publish benchmark numbers without listing durability policy, storage backend, data directory type, and limits. Those settings can change performance by more than the query optimizer change being measured.

For support reports, redact secrets but keep variable names visible. For example, say AIONDB_BOOTSTRAP_PASSWORD=<redacted> instead of omitting the variable entirely.