Deployment

Relata ships three deployment profiles from one binary. The SDK works identically across all three; only the runtime characteristics differ.

ProfileUse caseDefault capsStart command
freeEmbedded / single-process / dev / CIUnbounded (small datasets stay in RAM)RELATA_PROFILE=free relata serve
serverSingle-node productionRAM walls default-on at 1024 MBRELATA_PROFILE=server relata serve
clusterMulti-node distributed (alpha)Same as server, plus cluster coordinationRELATA_PROFILE=cluster relata serve

free is the default (lite was a legacy alias and is now rejected outright — use free).

Protocol doors — bring your existing client

RelataDB speaks 13 wire protocols from one binary: 8 compatibility doors (MongoDB, Postgres + pgvector, Redis, Neo4j HTTP/Bolt, ClickHouse HTTP/TCP, S3) plus 5 native (HTTP, gRPC, Arrow Flight, MCP, SPARQL). Your existing clients connect to Relata — you don't rewrite your app, you repoint host/port and use RELATA_BEARER_TOKEN as the password. See Compatibility & Doors for the full story.

Doors default to 127.0.0.1 so an unauthenticated port is never auto-exposed, and they auto-enable when RELATA_BEARER_TOKEN is set. To let another container/host/pod reach a door, override its bind and publish the port:

# Expose Mongo + Postgres + Redis off-loopback, on any profile (no license needed)
RELATA_BEARER_TOKEN=<token> \
RELATA_MONGO_BIND=0.0.0.0 \
RELATA_PG_BIND=0.0.0.0 \
RELATA_REDIS_BIND=0.0.0.0 \
RELATA_PROFILE=server relata serve

For the full Docker -p / Kubernetes containerPort wiring, TLS, and the security checklist, see Deploying Protocol Doors.

Profile defaults that bite

The server and cluster profiles enable the disk-first walls by default so you don't OOM in production:

  • RELATA_STORE_MAX_RAM_MB1024 MB on server/cluster (unbounded on free)
  • Graph RELATA_GRAPH_RAM_BUDGET_MB → 1024 MB
  • Identity RELATA_IDENTITY_RAM_BUDGET_MB → 1024 MB
  • DiskANN RELATA_DISKANN_MAX_RESIDENT → 1,000,000 resident/bucket

An explicit env var always overrides the profile default. The budgets are generous — small/medium deployments stay fully resident (no behaviour change).

Free — local dev

relata serve

Storage defaults to local disk at ./data/relata/objects (persistent, no config needed). Override with RELATA_LOCAL_DATA_DIR for a custom path, or AWS_ENDPOINT_URL for S3/MinIO.

Without RELATA_BEARER_TOKEN the server runs in dev mode (no auth, pgwire disabled). The warning is expected:

WARNING: RELATA_BEARER_TOKEN not set — running in unauthenticated mode (dev only)

LLM calls and telemetry are opt-in — leave RELATA_LLM_URL/RELATA_LLM_API_KEY and RELATA_OTLP_ENDPOINT unset for an air-gapped node. For demo / load-testing, disable rate limits directly:

RELATA_RATE_LIMIT_RPS=99999 RELATA_RATE_LIMIT_AUTH_FAIL_RPS=99999 relata serve

Server — single-node production

RELATA_PROFILE=server \
RELATA_BEARER_TOKEN=<your-strong-token> \
RELATA_PORT=9090 \
relata serve

Set RELATA_PLAINTEXT_OK=true only if you terminate TLS at a reverse proxy / sidecar.

Object-store persistence

Object-store persistence is always on — Relata defaults to local disk at RELATA_DATA_DIR/objects. RELATA_LOCAL_DATA_DIR overrides the path; AWS_ENDPOINT_URL selects S3 / MinIO / R2 / GCS / Azure Blob. WAL + Parquet snapshots persist across restarts.

Cold-restart RTO (measured at 10 M rows)

PhaseTime
WAL + Parquet flush (shutdown)~15 s
Cold-load from Parquet (restart, no warm cache)~55 s

Single-node RTO ≈ 1 minute at 10M-row scale. Paged backends + WAL replay are the production path for faster restarts on larger datasets.

For faster cold-load:

RELATA_LAZY_RESTART=true \
RELATA_HYDRATE_RECENT_SEGMENTS=5 \
relata serve

Lazy restart loads the manifest catalog only (O(manifest), not O(rows)); the newest N segments hydrate into RAM at startup and the rest hydrate on demand.

Cluster — multi-node (alpha)

RELATA_PROFILE=cluster \
NODE_ID=node-1 \
CLUSTER_ROLE=coordinator \
CLUSTER_PEERS=http://node-2:9090,http://node-3:9090 \
relata serve

(Plain NODE_ID / CLUSTER_ROLE / CLUSTER_PEERS — not RELATA_NODE_ID/RELATA_ROLE/RELATA_PEERS, which are different, unrelated vars. A real cluster node also needs RELATA_CLUSTER_SEED, RELATA_PUBLIC_URL, CLUSTER_AUTH_TOKEN, and — for local/dev without a real KMS key — RELATA_KMS_LOCAL_DEV=true; see Cluster Setup for the complete, tested list and a copy-pasteable 3-node example.)

RoleResponsibility
coordinatorQuery planning, request routing
readerRead-only query execution
writerWrite ingest + WAL
indexerBackground indexing (FTS, vectors, identity)

Cluster is alpha — petabyte / 200B-subscriber cardinality still needs sharding / cluster fan-out (epic #797).

Observability

VariableDefaultEffect
RELATA_LOG_FORMATprettyjson for production log shippers.
RELATA_LOG_LEVELinfoLog level.
RELATA_OTLP_ENDPOINTOTLP/HTTP traces endpoint. Unset = OpenTelemetry fully disabled.
RELATA_OTLP_SAMPLE_RATIO0.01Parent-based TraceID-ratio sampler.
RELATA_METRICS_PUBLICServe /metrics without a bearer token (Prometheus behind network-layer auth).

Graceful shutdown

The server handles SIGTERM gracefully:

  1. Stops accepting new requests.
  2. Drains in-flight queries (configurable drain timeout).
  3. Flushes the WAL + Parquet snapshot.
  4. Closes the HTTP/gRPC listeners.

Cold-restart RTO at 10M rows is ~1 minute (see above).

See also