Skip to content

ZeptoDB Configuration Reference

Last updated: 2026-07-19

ZeptoDB uses a YAML configuration file for server startup. Pass it with --config:

Terminal window
./zepto_server --config /etc/zeptodb/config.yaml

All fields are optional — defaults are production-safe. Only override what you need.



server:
port: 8123
auth:
enabled: false
server:
port: 8123
tls:
enabled: true
cert_path: /etc/zeptodb/cert.pem
key_path: /etc/zeptodb/key.pem
https_port: 8443
auth:
enabled: true
api_keys_file: /etc/zeptodb/keys.txt
jwt:
enabled: true
hs256_secret: ${JWT_SECRET}
expected_issuer: https://auth.example.com
rate_limit:
requests_per_minute: 1000
burst_capacity: 200
pipeline:
storage_mode: tiered
hdb_base_path: /data/zeptodb/hdb
server:
port: 8123
cluster:
enabled: true
node_id: 1
host: 10.0.1.1
port: 8123
rpc_port: 8223
peers:
- { id: 2, host: 10.0.1.2, port: 8123 }
- { id: 3, host: 10.0.1.3, port: 8123 }
health:
heartbeat_interval_ms: 1000
suspect_timeout_ms: 3000
dead_timeout_ms: 10000

HTTP server settings.

server:
port: 8123 # HTTP listen port
bind_address: 127.0.0.1 # Bind address (non-loopback exposure is explicit)
query_timeout_ms: 30000 # Auto-cancel queries after this duration (0 = no timeout)
max_request_body_mb: 64 # Max POST body size in MB
FieldTypeDefaultDescription
portint8123HTTP listen port
bind_addressstring127.0.0.1Network interface to bind
query_timeout_msint30000Query auto-cancel timeout (ms). 0 = disabled
max_request_body_mbint64Maximum request body size

Authentication and authorization.

auth:
enabled: true # false = bypass all auth (dev mode)
api_keys_file: /etc/zeptodb/keys.txt
jwt:
enabled: false
hs256_secret: "" # HS256 shared secret (mutually exclusive with rs256)
rs256_public_key_pem: "" # RS256 public key PEM file path
expected_issuer: "" # Validate JWT "iss" claim
expected_audience: "" # Validate JWT "aud" claim
verify_expiry: true
role_claim: zepto_role # JWT claim name for role
symbols_claim: zepto_symbols # JWT claim name for symbol whitelist
tenant_claim: tenant_id # JWT claim name for tenant binding
tables_claim: allowed_tables # JWT string-array claim for table ACL
rate_limit:
enabled: true
requests_per_minute: 1000 # Per-identity limit
burst_capacity: 200 # Max burst tokens
per_ip_rpm: 10000 # Per-IP limit (0 = disabled)
ip_burst: 500
audit:
enabled: true
log_file: /var/log/zeptodb/audit.log # Empty = stderr via spdlog
buffer_enabled: true # In-memory ring buffer for /admin/audit
public_paths: # Paths that never require auth
- /ping
- /health
- /ready
- /api/license
- /auth/login
- /auth/callback
- /auth/logout
- /auth/session # handler validates the Bearer token once
FieldTypeDefaultDescription
enabledbooltrueMaster auth switch
api_keys_filestringPath to API key store file
jwt.enabledboolfalseEnable JWT/OIDC authentication
jwt.hs256_secretstringHS256 shared secret
jwt.rs256_public_key_pemstringRS256 public key PEM path
jwt.expected_issuerstringRequired JWT issuer
jwt.expected_audiencestringRequired JWT audience
jwt.role_claimstringzepto_roleJWT claim for role
jwt.symbols_claimstringzepto_symbolsJWT claim for symbol list
jwt.tenant_claimstringtenant_idJWT claim for tenant binding
jwt.tables_claimstringallowed_tablesJWT string-array claim for table ACL
oidc.issuerstringOIDC issuer URL (auto-discovers JWKS, auth, token endpoints)
oidc.client_idstringOAuth2 client ID
oidc.client_secretstringOAuth2 client secret (use Vault/env in production)
oidc.redirect_uristringOAuth2 callback URL (e.g., http://host:8123/auth/callback)
oidc.audiencestringExpected audience claim (optional)
session.enabledboolfalseEnable server-side session store
session.ttl_sint3600Session lifetime (seconds)
session.refresh_window_sint300Extend session if active within this window
session.max_session_lifetime_sint28800Absolute session lifetime; idle refresh cannot extend past it
session.max_sessionsint10000Max concurrent sessions; capacity rejects new sessions after expired-session cleanup and never evicts a valid session
session.cookie_namestringzepto_sidSession cookie name
session.cookie_secureboolfalseSecure flag on cookie (set true with TLS)
session.cookie_httponlybooltrueHttpOnly flag on cookie
sso.enabledboolfalseEnable multi-IdP SSO identity provider
sso.cache_ttl_sint300Identity cache TTL
sso.cache_capacityint10000Max cached identities
rate_limit.requests_per_minuteint1000Per-identity rate limit
rate_limit.burst_capacityint200Token bucket burst size
rate_limit.per_ip_rpmint10000Per-IP rate limit
audit.log_filestringAudit log file path

TLS/HTTPS configuration.

tls:
enabled: false
cert_path: /etc/zeptodb/cert.pem
key_path: /etc/zeptodb/key.pem
ca_cert_path: "" # Optional: CA cert for mTLS
https_port: 8443
also_serve_http: false # Reserved; only one listener is served
FieldTypeDefaultDescription
enabledboolfalseEnable HTTPS
cert_pathstringServer certificate PEM
key_pathstringPrivate key PEM
ca_cert_pathstringCA cert for mutual TLS client verification
https_portint8443HTTPS listen port
also_serve_httpboolfalseReserved; the current server exposes one listener

Core data pipeline settings.

pipeline:
storage_mode: in_memory # in_memory | tiered | on_disk
arena_size_mb: 32 # Per-partition arena size
drain_batch_size: 256 # Ticks per drain batch
drain_threads: 1 # Number of drain threads
drain_sleep_us: 10 # Drain thread sleep (μs)
hdb_base_path: /data/zeptodb/hdb # HDB root directory
max_memory_mb: 0 # 0 = unlimited, else evict oldest partitions
recovery:
enabled: false
snapshot_path: /data/zeptodb/snapshots
FieldTypeDefaultDescription
storage_modestringin_memoryin_memory, tiered, on_disk
arena_size_mbint32Per-partition memory arena (MB)
drain_batch_sizeint256Ticks drained per batch
drain_threadsint1Parallel drain threads
hdb_base_pathstring/tmp/zepto_hdbHistorical database directory
max_memory_mbint0Memory limit; tiered mode currently requires 0 to retain SQL-visible RDB rows
recovery.enabledboolfalseLoad snapshot on startup
recovery.snapshot_pathstringSnapshot root containing atomically published CURRENT and generation manifests

Flush, tiering, Parquet, and S3 settings.

storage:
flush:
memory_threshold: 0.8 # Flush when arena usage exceeds this ratio
check_interval_ms: 1000
enable_compression: true # LZ4 compression for binary HDB
reclaim_after_flush: false # tiered pipeline rejects true until HDB SQL merge
auto_seal_age_hours: 1 # Seal partitions older than N hours
tiering:
enabled: false
warm_after_ns: 3600000000000 # 1 hour → warm (local SSD)
cold_after_ns: 86400000000000 # 24 hours → cold (S3)
drop_after_ns: 0 # 0 = no auto-drop
parquet:
compression: snappy # snappy | zstd | none
row_group_size_mb: 128
write_stats: true
s3:
enabled: false
bucket: my-zepto-bucket
prefix: hdb
region: us-east-1
endpoint_url: "" # Custom endpoint (MinIO, LocalStack)
use_path_style: false # true for MinIO
delete_local_after_upload: false
snapshot:
enabled: false
interval_ms: 60000 # Snapshot every 60s
path: /data/zeptodb/snapshots

When storage.snapshot.path is configured, graceful pipeline shutdown drains the ingest queue and publishes a final immutable generation. Recovery loads only the generation named by CURRENT and fails startup on manifest, column, type, row-count, or detectable payload-size/compression corruption. This is a single-writer graceful-restart guarantee, not abrupt-node-loss or power-loss durability: pipeline WAL replay, checksummed data, and complete file/directory fsync coverage remain open. STRING/SYMBOL generations are not published; graceful stop fails until durable StringDictionary metadata is implemented.


Multi-node distributed cluster settings.

cluster:
enabled: false
node_id: 1
host: 10.0.1.1
port: 8123
rpc_port: 8223 # TCP RPC port (0 = port + 100)
enable_remote_ingest: true
peers:
- { id: 2, host: 10.0.1.2, port: 8123 }
- { id: 3, host: 10.0.1.3, port: 8123 }
health:
heartbeat_interval_ms: 1000
suspect_timeout_ms: 3000
dead_timeout_ms: 10000
heartbeat_port: 9100
replication:
factor: 2 # Replication factor (1 = no replication)
wal_batch_size: 1024
coordinator_ha:
enabled: false
lease_name: zepto-coordinator
lease_namespace: default
lease_duration_s: 15
renew_interval_s: 5
FieldTypeDefaultDescription
enabledboolfalseEnable cluster mode
node_idintUnique node identifier
hoststringThis node’s advertised hostname/IP
rpc_portintport+100TCP RPC port for inter-node communication
health.heartbeat_interval_msint1000Heartbeat send interval
health.suspect_timeout_msint3000Mark node SUSPECT after this silence
health.dead_timeout_msint10000Mark node DEAD after this silence
replication.factorint2Number of copies per partition

Nodes can also be added/removed at runtime via the Admin API:

Terminal window
# Add a node
curl -X POST https://zepto:8443/admin/nodes \
-H "Authorization: Bearer $ADMIN_KEY" \
-d '{"id":4,"host":"10.0.1.4","port":8123}'
# Remove a node
curl -X DELETE https://zepto:8443/admin/nodes/4 \
-H "Authorization: Bearer $ADMIN_KEY"

Query execution settings.

query:
parallel:
enabled: true
num_threads: 0 # 0 = hardware_concurrency
row_threshold: 100000 # Min rows for parallel execution
resource_isolation:
enabled: false
realtime_cores: [0, 1] # CPU cores for ingestion
analytics_cores: [2, 3, 4, 5] # CPU cores for queries
drain_cores: [6] # CPU cores for drain threads
FieldTypeDefaultDescription
parallel.enabledboolfalseEnable parallel query execution
parallel.num_threadsint0Worker threads (0 = auto)
parallel.row_thresholdint100000Min rows to trigger parallel scan
resource_isolation.realtime_coresint[]CPU affinity for ingestion
resource_isolation.analytics_coresint[]CPU affinity for queries

External data feed handlers.

feeds:
kafka:
enabled: false
brokers: localhost:9092
topic: market-data
group_id: zepto-consumer
auto_offset_reset: latest # latest | earliest
format: json # json | binary | json_human
price_scale: 10000.0
poll_timeout_ms: 100
batch_size: 1024
commit_mode: after_ingest # after_ingest | auto
backpressure_retries: 3
backpressure_sleep_us: 100
symbol_map:
AAPL: 1
GOOGL: 2
pulsar:
enabled: false
service_url: pulsar://localhost:6650
topic: persistent://public/default/market-data
subscription_name: zepto-consumer
subscription_type: shared # shared | exclusive | failover | key_shared
initial_position: latest # latest | earliest
format: json # json | binary | json_human
receive_timeout_ms: 100
max_messages_per_poll: 1024
receiver_queue_size: 1000
table_name: trades # optional, empty = legacy table_id 0
backpressure_retries: 3
backpressure_sleep_us: 100
fix:
enabled: false
host: fix-gateway.example.com
port: 9876
username: zepto
password: ${FIX_PASSWORD}
use_tls: true
reconnect_interval_ms: 5000
heartbeat_interval_ms: 30000
itch:
enabled: false
host: nasdaq-itch.example.com
port: 1234

Logging, metrics, and monitoring.

observability:
log:
level: info # trace | debug | info | warn | error
directory: /var/log/zeptodb
access_log: true # Structured JSON access log per request
slow_query_ms: 100 # Log queries slower than this
metrics:
capture_interval_ms: 3000 # Internal metrics snapshot interval
max_memory_bytes: 262144 # 256KB ring buffer for /admin/metrics/history
response_limit: 600 # Max snapshots per API response
prometheus:
enabled: true # Expose /metrics endpoint

The production binary currently consumes explicit CLI options. Its secure defaults are: zero synthetic ticks, a loopback listener, authentication, identity/IP rate limiting, audit logging, a 64 MiB request-body ceiling, and a 30-second cooperative query timeout.

OptionDefaultProduction behavior
--bind HOST127.0.0.1A plaintext non-loopback listener is rejected unless --allow-plaintext-http acknowledges trusted external TLS termination
--tls-cert PATH + --tls-key PATHEnables direct HTTPS; both readable PEM files are required
--tls-ca PATHEnables mandatory client-certificate verification using the supplied CA
--secure-cookieoffMarks session cookies Secure behind a TLS-terminating proxy; direct TLS enables it automatically
--api-keys-file PATHZEPTO_API_KEYS_FILELoads the hash-only API-key store; an absent/empty credential method fails startup
--bootstrap-dev-keysoffExplicitly creates and prints local development keys; never use in production
--no-bootstrap-dev-keysoffCompatibility no-op; bootstrap is already disabled by default
--disable-rate-limitoffExplicit development-only opt-out
--disable-auditoffExplicit development-only opt-out
--max-request-bytes N67108864Hard HTTP request-body limit
--query-timeout-ms N30000Cooperative cancellation timeout; the worker waits for local execution to stop and remote RPC work is not cancelled; 0 disables it
--allow-experimental-distributed-queriesoffEnables the legacy multi-node SELECT path without end-to-end request-owned row caps/cancellation; production default rejects it with 503
--oidc-issuer URL + --oidc-client-id ID + --oidc-redirect-uri URLEnables strict HTTPS OIDC discovery and server-side sessions; redirect must be HTTPS except for exact loopback HTTP
--oidc-client-secret-file PATH / --oidc-client-secret-env NAMEZEPTO_OIDC_CLIENT_SECRETPreferred mutually exclusive secret sources; empty/unreadable sources fail startup
--oidc-client-secret SECRETCompatibility input; process arguments may expose it, so do not use it in production
--oidc-audience AUDclient IDExpected token audience
--ticks N0Synthetic demo data is opt-in
--storage-mode tiered --hdb-dir PATHpureTiered mode requires an explicit directory and stores graceful-shutdown recovery snapshots under PATH/_rdb_snapshots
--acknowledge-incomplete-durabilityoffMandatory with tiered/cold storage until abrupt-loss WAL recovery and full HDB reads are complete

--storage-mode, cold-tier format/layout, numeric arguments, malformed node specifications, incomplete options, and unknown options fail closed. An existing corrupt _schema.json also fails tiered startup; it is never replaced with a fresh demo catalog. Detected structural corruption in a published recovery snapshot also fails startup. Tiered mode currently retains flushed partitions in memory because general SQL is not fully HDB-aware. Graceful shutdown publishes and reloads a complete RDB snapshot, but abrupt process/node-loss WAL recovery, payload checksums, and complete fsync coverage remain production blockers; a PVC plus --hdb-dir must not yet be described as complete database durability.

For reverse-proxy TLS in Kubernetes, use all three options together:

Terminal window
--bind 0.0.0.0 --allow-plaintext-http --secure-cookie

OIDC client secrets should be mounted as a file or injected through an environment variable. Supplying the literal --oidc-client-secret value may expose it through process listings and workload manifests. Discovery fails closed unless the returned issuer matches exactly and the authorization, token, and JWKS endpoints are all present and HTTPS.

OptionDefaultProduction behavior
--flight-host HOST127.0.0.1Non-loopback plaintext Flight fails unless the development override is explicit
--tls-cert PATH + --tls-key PATHShared direct TLS for Flight and bundled HTTP
--api-keys-file PATHZEPTO_API_KEYS_FILERequired readable key store with at least one active credential unless a development override is explicit
--bootstrap-dev-keysoffExplicit local-only key creation; prints raw keys once
--query-timeout-ms N30000Cooperative Flight read timeout; 0 disables
--allow-insecure-flightoffDevelopment-only plaintext Flight override; does not affect HTTP
--allow-plaintext-httpoffSeparate development-only bundled HTTP plaintext override
--allow-non-atomic-putoffExperimental non-atomic DoPut; never enable for production
--ticks N0Synthetic rows are opt-in

Any config value can be overridden with ${ENV_VAR} syntax in the YAML file. The server resolves these at startup.

auth:
jwt:
hs256_secret: ${JWT_SECRET}
feeds:
fix:
password: ${FIX_PASSWORD}
storage:
s3:
bucket: ${S3_BUCKET}

Common environment variables:

VariableDescription
ZEPTO_PORTOverride server.port
ZEPTO_CONFIGConfig file path (alternative to --config)
ZEPTO_API_KEYS_FILEHash-only API-key store used by zepto_http_server
ZEPTO_CLUSTER_SECRET_FILERecommended path to the shared cluster RPC secret (minimum 32 bytes)
ZEPTO_CLUSTER_SECRETInline cluster RPC secret alternative; mutually exclusive with the file source
JWT_SECRETJWT HS256 shared secret
FIX_PASSWORDFIX gateway password
S3_BUCKETS3 bucket name
AWS_REGIONAWS region for S3

The production zepto_data_node and zepto_ingest_node binaries require a valid cluster secret. zepto_http_server requires one for --ha, --add-node, and runtime POST /admin/nodes. The explicit --allow-insecure-cluster override is for isolated development only. Cluster RPC authentication requires OpenSSL and does not provide transport encryption.


ZeptoDB resolves secrets using a priority chain:

1. HashiCorp Vault KV v2 (if VAULT_ADDR is set)
2. Kubernetes file secrets (if /var/run/secrets/zeptodb/ exists)
3. Environment variables (fallback)

Configure Vault:

secrets:
vault:
enabled: true
address: https://vault.example.com:8200
mount_path: secret/data/zeptodb
token_path: /var/run/secrets/vault/token

All ${VAR} references in the config file are resolved through this chain. Secrets are never logged or exposed via API.


See also: HTTP API Reference · SQL Reference · Production Deployment