> ## Documentation Index
> Fetch the complete documentation index at: https://docs.experio.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Graph backend (Neo4j & FalkorDB)

> Configure the active graph database, run migrations, and understand Neo4j vs FalkorDB behavior

## 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

Set **`GRAPH_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](/admin-guide/system-settings#db-settings) 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.

Product and engineering decisions for the reverse direction are documented in
[FalkorDB → Neo4j migration research](/graph-migration/falkordb-to-neo4j-migration-research).

## Behavioral differences

| Topic                          | Neo4j                                                                 | FalkorDB                                                         |
| ------------------------------ | --------------------------------------------------------------------- | ---------------------------------------------------------------- |
| **Cypher**                     | Full Neo4j 5.x surface used by Experio                                | Subset; LLM Cypher generation uses Falkor-specific dialect notes |
| **Relationship fan-out stats** | Uses Neo4j **5.23+** scoped `CALL (triple) { … }` batch introspection | Batch path skipped; stats use a safe fallback                    |
| **Typical production default** | Common default (`keep_alive`)                                         | Available in cluster (`keep_down` by default)                    |

## 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, and
`initdb` no longer wait for a graph DB to be healthy.

### Default state

| Service    | Scaling mode | Replicas | Notes                                  |
| ---------- | ------------ | -------- | -------------------------------------- |
| `neo4j`    | `keep_alive` | 1        | Matches historical production behavior |
| `falkordb` | `keep_down`  | 0        | No cost until you enable it            |

Seeded connection defaults (via `initdb` → `seed_config`):

* `FALKOR_URI`: `redis://falkordb:6379` (cluster internal DNS)
* `NEO4J_URI`: `neo4j://neo4j:7687`

Passwords come from Omnistrate secrets `neo4jPassword` and `falkordbPassword`.
See [Omnistrate deployment](/omnistrate#omnistrate-secrets).

### 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

Changes are applied by the scale-to-zero sidecar on the server pod (polls every
\~60s). Allow a few minutes after toggling before expecting connectivity.

### Migration window (both providers up)

Graph migration requires **both** backends reachable:

1. Set **`neo4j`** and **`falkordb`** to **`keep_alive`** in ServiceConfiguration
2. Wait until both pass connectivity checks (Admin → System Settings → provider probe,
   or inspect `/health/` — graph may show `checks.neo4j` unhealthy until warm)
3. Run migration from **Admin → Settings → Graph migration**
4. Switch **`GRAPH_PROVIDER`** in System Settings
5. 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

Chat and graph ingestion need the active provider up; other admin features may work
while status is `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. With `neo4j` on `keep_alive`, this
is rarely an issue in steady state.

For how relationship attributes interact with graph introspection on Neo4j, see
[Relationship attributes](/architecture/relationship-attributes).

## Local development

When using the devcontainer, FalkorDB and its Browser UI are available for ad-hoc Cypher. See
[FalkorDB Browser (local development)](/local-development/falkordb-browser).
