Configuration Reference
A consolidated reference for the knobs across the CLI and the server.
CLI (patinadb-cli)
patinadb <db-path> <subcommand> [flags]
| Subcommand | Flags |
|---|---|
query | --json, --at <engram-id> |
log | — |
diff | <engram-id>, --json |
diff-range | <from> <to>, --identity-props <list>, --json |
<from> accepts empty for the empty graph; --identity-props defaults to
qualified_name,fqn,name (none disables move pairing).
Server (patinadb-raft)
| Flag | Default | Notes |
|---|---|---|
--config <path> | off | Load settings from a YAML config file (see below). |
--print-config-schema | off | Print a JSON Schema for the config file to stdout and exit. |
--id <u64> | required | Unique Raft node id (here or in the config file). |
--addr <host:port> | required | HTTP (REST + management + peer RPC). |
--db <dir> | required | Database root (one subdir per database). |
--bootstrap | off | Self-init a single-voter cluster. |
--join <member> | off | Auto-join an existing member as a learner on startup. Excludes --bootstrap. |
--bolt-addr <addr> | 127.0.0.1:7687 | Bolt listener; "" disables Bolt. |
--advertised-addr <a> | = --bolt-addr | Public Bolt address for routing behind a proxy. |
--auth-user <name> | neo4j | Auth username. |
--auth-password <p> | "" | Shared password. Empty = no auth, fail-closed: the node won’t start without --insecure-disable-auth. |
--insecure-disable-auth | off | Explicitly allow running open (empty password). Trusted networks only. |
--tls-cert <path> | off | PEM cert chain. With --tls-key, serves the HTTP plane (REST + peer RPCs) over HTTPS. |
--tls-key <path> | off | PEM private key (required with --tls-cert). |
--tls-ca <path> | system roots | PEM CA peers verify each other with (self-signed / private-CA clusters). |
--require-metrics-auth | on (default) | Gate GET /metrics behind Basic auth. Default-on since series carry db=<name> labels. |
--insecure-open-metrics | off | Opt out of metrics auth — serve /metrics open on a private monitoring network. |
--query-timeout-secs <n> | 300 | Per-request budget for a REST /cypher read; overrun → 503 (deadline, not a hard cancel). 0 = off. |
--max-concurrent-requests <n> | 512 | Cap on in-flight HTTP requests; excess shed with 503. 0 = unlimited. |
--readiness-max-lag <n> | 50 | /ready apply-lag tolerance: report not ready (503 lagging) when last_log_index − last_applied exceeds this. See Day-2 operations. |
--otel-endpoint <url> (PATINADB_OTEL_ENDPOINT) | unset | Enable request/trace correlation (X-Request-Id + inbound W3C traceparent) and force structured JSON logs for OpenTelemetry-collector ingestion. See Day-2 operations. |
--allow-csv-dir <dir> | deny-all | Directory LOAD CSV FROM 'file://…' may read from. Repeatable. Unset ⇒ every LOAD CSV file read is refused. See Cypher file I/O. |
--allow-export-dir <dir> | deny-all | Directory the CSV export procs (patinadb.export.*) may write to. Repeatable. Unset ⇒ every export write is refused. |
--rbac-closed (PATINADB_RBAC_CLOSED) | off | Closed-mode RBAC: deny a non-admin any database it holds no explicit grant on. See Authentication & TLS. |
--telemetry-degrade-override-until <value> (PATINADB_TELEMETRY_DEGRADE_OVERRIDE) | unset | Time-boxed break-glass: keep writes enabled past a missed telemetry grace window until an absolute deadline. See Day-2 operations. |
Environment: PATINADB_AUTH_PASSWORD sets the auth password (preferred over a
shell flag).
YAML config file (--config)
Instead of (or alongside) flags, point the server at a YAML file mirroring the settings above:
# node.yaml
id: 1
addr: "127.0.0.1:21001"
db: "/var/lib/patinadb"
bootstrap: true
bolt_addr: "0.0.0.0:7687"
auth_user: "neo4j"
# auth_password: prefer the PATINADB_AUTH_PASSWORD env var over the file
query_timeout_secs: 30
max_concurrent_requests: 256
patinadb-raft --config node.yaml
Every field is optional; an absent key falls back to the CLI flag, then to the
built-in default. The YAML key names match the long flag names with -
replaced by _ (e.g. --bolt-addr → bolt_addr). Unknown keys are rejected so
a typo fails loudly.
Precedence (highest wins): an explicitly-passed CLI flag (or its bound env
var, e.g. PATINADB_AUTH_PASSWORD) > the config file > the built-in
default. A flag left at its clap default does not override a value set in the
file — only flags the operator actually typed do. The required settings (id,
addr, db) may come from either the file or flags; if neither supplies one,
startup fails with a clear error.
Config JSON Schema (--print-config-schema)
patinadb-raft --print-config-schema prints a JSON Schema (Draft 7) for the
config file — every property carries its description (lifted from the Rust
doc-comments) so editors can offer autocompletion and validation. It works
without any other arguments:
patinadb-raft --print-config-schema > patinadb-config.schema.json
Resource limits & quotas
Guards that bound the cost of a single query so one statement can’t exhaust
memory or run unbounded. The two engine budgets are environment variables
(they apply to the embedded library and every server built on it); the two
server request limits are flags (see the patinadb-raft table above).
| Limit | Where | Default | Purpose |
|---|---|---|---|
PATINADB_MAX_HOPS | env | 1000 | Depth cap for an unbounded variable-length hop ([*], or [*..n] with n unset). An explicit [*a..b] in the query always wins. Prevents runaway traversal on a cyclic graph. |
PATINADB_CARTESIAN_CAP | env | 10000 | Max rows a disjoint (cross-product) multi-MATCH may produce before the query errors. Stops an accidental N×M blow-up. |
PATINADB_MAX_AGG_ROWS | env | 5000000 | Cap on the O(input)/O(result) row buffers behind GROUP BY/aggregate, a full (non-top-K) ORDER BY, UNION dedup, and a hash-join build side. A clear error over the cap instead of a silent OOM. See Query Planning. |
PATINADB_MAX_CAPTURE_OPS | env | 5000000 | Cap on the number of resolved ops a single embedded write statement (or the Raft leader’s resolve step) may buffer before recording one engram/Raft entry. A whole-graph SET/bulk CREATE over the cap fails with a clear error pointing at CALL {…} IN TRANSACTIONS instead of risking an OOM or a giant single Raft entry. |
PATINADB_MAX_ALGO_WORK | env | ~1e10 | Static work-budget backstop for O(V·E) read procedures (betweenness/closeness): refuses a call whose estimated n·(n+e) exceeds this, so a Reader can’t trigger unbounded compute even without --query-timeout-secs. See Day-2 operations. |
PATINADB_MAX_SNAPSHOTS | env | unlimited (0/unset) | Prunes on-disk periodic time-travel snapshot files down to the N most recent (+ every pinned/tagged one) after each snapshot-taking commit. Embedded/CLI have no other retention driver, so a long-lived write-heavy embedded db otherwise grows snapshot files unbounded; pruning only slows reconstruction of an old, out-of-window engram — every AS OF result stays byte-identical. Also settable via Dataset::with_max_snapshots in the embedded API. |
--query-timeout-secs | server flag | 300 | Per-request wall-clock budget for a REST read; overrun → 503. 0 = off. |
--max-concurrent-requests | server flag | 512 | Max in-flight HTTP requests; excess shed with 503. 0 = unlimited. |
Set an env budget to 0 (or unset) to fall back to the built-in default. Tighten
them as DoS guards on a shared node, or raise PATINADB_MAX_HOPS for a
genuinely deep graph. A RETURN … LIMIT k is the normal way to bound result
size — there is no implicit result cap (an unlimited query streams every row).
For observability, set PATINADB_SLOW_QUERY_MS (server env, off by default)
to log a WARN for any REST query slower than that many milliseconds — carrying
the query’s normalized shape (literals + $params folded to ?), not raw
values. Per-shape latency stats are also served at GET /mgmt/queries.
Commercial entitlements
The server resolves a set of commercial caps (cluster HA size, combined
node+edge scale, database count, history-retention window, and two feature
gates) either from the hard-coded Community ceiling or from a signed license
token’s entitlement claims. This is configured entirely by which license you
install (--license / PATINADB_LICENSE / <db-root>/license.key — see
Licensing & Telemetry), not by a server flag. See
Editions & Limits for the full Community/Pro/Enterprise table,
what each limit does when you hit it, and how to read a running node’s
resolved tier + live usage via GET /version (also scraped onto
patinadb_entitlement_usage_ratio{axis} / patinadb_entitlement_limit{axis}
Prometheus gauges).
Cache memory budget
patinaDB can keep a governed, RAM-budgeted cache of decoded objects / adjacency
/ query results above redb’s page cache. It is opt-in: with PATINADB_CACHE_LIMIT
unset (or 0) the cache is entirely off — only the OS/redb page cache and the
existing plan/stats caches are used, at zero residual cost.
The budget derives from a cgroup-aware total (the real ceiling the kernel
OOM-kills at in a container, not the host’s RAM): cgroup v2 memory.max →
v1 memory.limit_in_bytes → host MemTotal, taking min(cgroup, MemTotal).
From that total, PATINADB_MEMORY_LIMIT is patinaDB’s own-heap ceiling (not
including the OS page cache), and four regions are carved from it. Each knob is
an absolute size (8GiB), a fraction of its parent (40%), or auto;
precedence is explicit-absolute > fraction > default, and fractions compose
against the resolved parent.
| Env var | Region | Default | Parent |
|---|---|---|---|
PATINADB_MEMORY_LIMIT | own-heap ceiling (excl. page cache) | auto = TOTAL − min_free | discovered TOTAL |
PATINADB_CACHE_LIMIT | cache pool (L1/L2/L3) — unset/0 disables caching | 40% | MEMORY_LIMIT |
PATINADB_WORK_MEM_LIMIT | action reserve (concurrent query working memory) | 45% | MEMORY_LIMIT |
PATINADB_MEM_HEADROOM | transient-spike / allocator-slop / OOM safety | 15% | MEMORY_LIMIT |
PATINADB_CACHE_MIN_FREE | page-cache floor (system free RAM kept resident for redb L0) | max(1GiB, 10%) | discovered TOTAL |
Every knob is also a patinadb-raft flag (--memory-limit, --cache-limit,
--work-mem-limit, --mem-headroom, --cache-min-free) and a YAML config key
(memory_limit, cache_limit, work_mem_limit, mem_headroom,
cache_min_free), with the same explicit-flag/env > file > default
precedence as every other setting.
The budget is validated at startup and fails loud (the node refuses to boot)
when it over-commits — CACHE_LIMIT + WORK_MEM_LIMIT + HEADROOM ≤ MEMORY_LIMIT
and MEMORY_LIMIT + CACHE_MIN_FREE ≤ TOTAL — with an error naming the offending
knobs and the resolved bytes. When enabled, the fully-resolved budget (bytes per
region) is logged at startup so it is never a mystery.
Example — a container with memory.max=16GiB, PATINADB_CACHE_LIMIT=40% and
otherwise defaults: TOTAL=16GiB, min_free≈1.6GiB, MEMORY_LIMIT≈14.4GiB
(TOTAL − min_free), then Cache ≈5.8GiB · Actions ≈6.5GiB · Headroom ≈2.2GiB.
Set PATINADB_MEMORY_LIMIT=10GiB to leave more RAM to the page cache on a
read-heavy deployment.
Internal defaults (informational)
These are not user-configurable flags today, but are useful to know:
| Setting | Value |
|---|---|
| Snapshot interval | every 50 commits |
| Raft election timeout | 750–1500 ms |
| Raft heartbeat | 250 ms |
| BM25 parameters | k1 = 1.2, b = 0.75 |
| Full-text prefix/fuzzy expansion cap | 256 terms |
| Bolt streaming channel | 256 records (bounded) |
| Default database name | default |
On-disk layout
The --db directory (server) or database path (embedded) contains the redb
tables for the graph, the property/compound indexes, the engram log and
snapshots, the full-text catalog and index data, and — for the server — the
persistent Raft log and state-machine metadata. Back up the whole directory as a
unit. For a server, each database is a subdirectory of --db.