Deployment
Relata ships three deployment profiles from one binary. The SDK works identically across all three; only the runtime characteristics differ.
| Profile | Use case | Default caps | Start command |
|---|---|---|---|
free | Embedded / single-process / dev / CI | Unbounded (small datasets stay in RAM) | RELATA_PROFILE=free relata serve |
server | Single-node production | RAM walls default-on at 1024 MB | RELATA_PROFILE=server relata serve |
cluster | Multi-node distributed (alpha) | Same as server, plus cluster coordination | RELATA_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 serveFor 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_MB→ 1024 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 serveStorage 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 serveServer — single-node production
RELATA_PROFILE=server \
RELATA_BEARER_TOKEN=<your-strong-token> \
RELATA_PORT=9090 \
relata serveSet 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)
| Phase | Time |
|---|---|
| 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 serveLazy 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.)
| Role | Responsibility |
|---|---|
coordinator | Query planning, request routing |
reader | Read-only query execution |
writer | Write ingest + WAL |
indexer | Background indexing (FTS, vectors, identity) |
Cluster is alpha — petabyte / 200B-subscriber cardinality still needs sharding / cluster fan-out (epic #797).
Observability
| Variable | Default | Effect |
|---|---|---|
RELATA_LOG_FORMAT | pretty | json for production log shippers. |
RELATA_LOG_LEVEL | info | Log level. |
RELATA_OTLP_ENDPOINT | — | OTLP/HTTP traces endpoint. Unset = OpenTelemetry fully disabled. |
RELATA_OTLP_SAMPLE_RATIO | 0.01 | Parent-based TraceID-ratio sampler. |
RELATA_METRICS_PUBLIC | — | Serve /metrics without a bearer token (Prometheus behind network-layer auth). |
Graceful shutdown
The server handles SIGTERM gracefully:
- Stops accepting new requests.
- Drains in-flight queries (configurable drain timeout).
- Flushes the WAL + Parquet snapshot.
- Closes the HTTP/gRPC listeners.
Cold-restart RTO at 10M rows is ~1 minute (see above).
See also
- Deploying Protocol Doors — bind vars, Docker
-ppublishing, KubernetescontainerPort, cross-host reachability - Compatibility & Doors — connection strings and 3-step quickstarts per protocol
- Cluster Setup — full multi-node walkthrough, a tested local 3-node recipe, and the non-obvious gotchas
- Kubernetes Deployment — the Helm-chart production path
- Environment Variables — full reference
- Limits & Caveats — capacity & scaling