Overview
Experio stores the knowledge graph (ontology instances, document relationships, embeddings on graph nodes) against either Neo4j or FalkorDB. Exactly one backend is active per deployment. The application routes reads and writes through a shared abstraction layer so ingestion, chat retrieval, and admin tools stay consistent.Choosing the active backend
SetGRAPH_PROVIDER to neo4j or falkordb in Admin > Settings > System Settings (DB category). Connection
fields for the inactive provider remain stored but are ignored until you switch.
See the DB settings reference for all keys. After changing provider or
connection details, validate connectivity using the dashboard flow (including the reachability probe surfaced when
switching providers).
Graph migration (staff)
Staff can copy data between backends from Admin > Settings > Graph migration:- Neo4j → FalkorDB and FalkorDB → Neo4j jobs stream progress over a WebSocket.
- Use prerequisites on that page (backup, connectivity) before starting a long run.
Behavioral differences
FalkorDB resilience & query limits
- Per-query memory cap — FalkorDB is started with
QUERY_MEM_CAPACITYset to 1 GiB. A single query that exceeds the cap is terminated by FalkorDB withQuery's mem consumption exceeded capacityinstead of pushing the container toward its memory limit (and an OOM restart). If a legitimate analytical query hits the cap, narrow the query; the cap is defined in the deployment spec (FALKORDB_ARGS). - Fail-fast on outages — graph calls use a 60s read timeout. While FalkorDB is
restarting (it reloads its dataset into memory and answers
LOADINGduring that window), chat and ingestion graph queries fail quickly with a provider-unavailable error instead of hanging. Expect/health/to reportstatus: degradeduntil the reload completes, then queries recover automatically — no server restart is needed.
Omnistrate / cluster deployment
Both Neo4j and FalkorDB run as internal cluster services with manual scale-to-zero. They are independent of platform boot — server, workers, andinitdb no longer wait for a graph DB to be healthy.
Default state
Seeded connection defaults (via
initdb → seed_config):
FALKOR_URI:redis://falkordb:6379(cluster internal DNS)NEO4J_URI:neo4j://neo4j:7687
neo4jPassword and falkordbPassword.
See Omnistrate deployment.
Controlling graph DB replicas
Use Django admin ServiceConfiguration (same UI as JupyterLab scale-to-zero):keep_alive— maintain 1 replica (use for the active provider)keep_down— maintain 0 replicas (use for the inactive provider to save cost)auto— manual strategy defaults to 1 replica; prefer explicit modes above
Migration window (both providers up)
Graph migration requires both backends reachable:- Set
neo4jandfalkordbtokeep_alivein ServiceConfiguration - Wait until both pass connectivity checks (Admin → System Settings → provider probe,
or inspect
/health/— graph may showchecks.neo4junhealthy until warm) - Run migration from Admin → Settings → Graph migration
- Switch
GRAPH_PROVIDERin System Settings - Set the inactive backend to
keep_down
Health monitoring
GET /health/ reports the active graph provider under checks.neo4j (legacy key
name; includes provider: neo4j | falkordb). Graph downtime does not fail the
whole endpoint:
status: degraded— platform OK, graph unavailable (expected during scale-to-zero)status: unhealthy— Postgres, Redis, RabbitMQ, or LLM failed
degraded.
Schema cache
On server startup a background thread pre-warms the graph schema cache in Redis (24h TTL). If the graph is down at boot, warming fails softly and the first chat query may be slower until cache is populated. Withneo4j on keep_alive, this
is rarely an issue in steady state.
The cache includes relationship fan-out statistics (fan_out_risk, max distinct
targets per source, max distinct sources per target) computed from live graph data.
After upgrading or switching graph providers, refresh the schema cache so fan-out
stats and aggregated property types reflect the active backend.
For how relationship attributes interact with graph introspection, see
Relationship attributes.