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

# Data layer: PostgreSQL, Redis and MongoDB

> What each store holds on a self-hosted xpander install, which can be external (PostgreSQL on RDS, Valkey or MemoryDB with the search module), which cannot (MongoDB, Supabase's Postgres), and how to bring your own.

On xpander's cloud, xpander operates the data tier. On Hybrid and Air-Gapped installs it runs in your cluster, and two of the stores can be replaced by managed services you already run.

## What each store holds

| Store                              | Holds                                                                             | External mode                          |
| ---------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------- |
| PostgreSQL 16                      | Execution records and activity threads, shared memories, and one schema per agent | Yes                                    |
| Redis Stack (`redis-stack-server`) | Queues, cache, and knowledge-base vectors as RediSearch (`FT.*`) indexes          | Yes, with the search module            |
| MongoDB                            | Catalog and monitoring stores                                                     | No; always a chart-managed StatefulSet |
| Supabase's own PostgreSQL 15       | Sign-in, storage metadata; requires extensions managed services do not ship       | No; always in-cluster                  |

In-cluster is the default: chart-managed StatefulSets on your StorageClass, SSD-backed. Production sizing on Air-Gapped: xpander's PostgreSQL 50 GiB, Supabase PostgreSQL 50 GiB, Supabase Storage 50 GiB and up, MongoDB 20 GiB, Redis 8 GiB, plus about 50 GiB for the registry mirror. Set `--storage-class <name>` if the cluster default is not the one you want.

## What is stored where

### Supabase's PostgreSQL (database `postgres`)

| Tables                                                                                                                                              | Hold                                                                                                                                    |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `ai_agents`                                                                                                                                         | The agent record: name, instructions, model and harness settings                                                                        |
| `agent_executions_history`                                                                                                                          | Tasks: `status`, `internal_status`, `source_client`, the `is_gateway` and `is_async` flags, `title`, `channel`                          |
| `connector`, `connector_status_updates`                                                                                                             | API connectors and the status changes of their creation pipeline                                                                        |
| `agent_asset_binding`                                                                                                                               | Skill bindings: `asset_type`, `auth_mode`, `policy`                                                                                     |
| `organization_api_keys`                                                                                                                             | API keys as prefix, last four characters, hash and a `secret_ref`; never the key itself                                                 |
| `llm_providers`, `model_prices`, `byok_model_prices`                                                                                                | Provider entries and the prices per model, xpander's and the ones you set                                                               |
| `live_surfaces`                                                                                                                                     | Live surfaces                                                                                                                           |
| `organization_environments`                                                                                                                         | Locations                                                                                                                               |
| `user_groups`, `group_members`, `user_group_oidc_links`, `organization_oidc_groups`, `organization_oidc_group_settings`, `organization_oidc_config` | User groups and their members, the SSO group links, the group values seen at sign-in, the groups-claim settings, the OIDC configuration |
| `vault_secret`, with `vault.secrets` and `vault.decrypted_secrets`                                                                                  | Credentials, through Supabase Vault                                                                                                     |
| `auth.*`                                                                                                                                            | Sign-in (GoTrue)                                                                                                                        |
| `storage.*`                                                                                                                                         | File metadata                                                                                                                           |
| `spend_watchdog.*`                                                                                                                                  | Budget enforcement                                                                                                                      |

### xpander's PostgreSQL 16 (database `xpander`)

| Schema          | Holds                                                                                                                                                                                                                     |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `xp_tiered`     | `executions`: one row per execution with `execution_id`, `agent_id` and `data`, the full execution JSON, including `harness_cli`, `llm_model_name`, `mcp_servers` and any `hitl_request`. `activity_threads`: the threads |
| `xp_shared`     | `memories` and `memory_settings`                                                                                                                                                                                          |
| `ag_<agent id>` | One schema per agent: sessions, memories, approvals, schedules and their runs, metrics, knowledge, learnings, evaluation runs, and a schema-version table                                                                 |

Isolation between agents is a schema per agent in this one database.

### MongoDB

| Collection                                                       | Holds                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `monitoring.audit`                                               | The audit log. Fields `organization_id`, `user_id`, `event_type`, `timestamp`, `metadata`, `expires_at`. Event types include `add_skill`, `change_llm_secrets`, `change_oidc_settings`, `change_org_default_llm_config`, `connect_connector`, `create_agent`, `create_api_key`, `create_knowledge_base`, `delete_agent`, `deploy_agent`, `read_secret`, `update_agent`, `update_secret`, `use_secret`, `user_login`, `user_logout`, `workspace_tool_invoked` |
| `monitoring.cost_ledger`                                         | One row per execution at token level: `model_id`, `tier`, input, output and cache tokens, `cost_usd`, `nominal_cost_usd`, `is_byok`                                                                                                                                                                                                                                                                                                                          |
| `monitoring.monitor`                                             | Monitoring records                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `billing.wallet_ledger`, `billing.wallet_usage_rollups`          | Credits in millicredits per meter, with tokens, model and cycle, and their rollups                                                                                                                                                                                                                                                                                                                                                                           |
| `catalog.openapi_specs`, `catalog.operations`, `catalog.schemas` | The skill catalog's OpenAPI specs, their operations and schemas                                                                                                                                                                                                                                                                                                                                                                                              |

### Looking inside from the cluster

The passwords come from the `xpander-generated-keys` secret. Nothing below prints one.

```bash theme={"dark"}
# xpander's PostgreSQL. The postgres Service resolves to the in-cluster StatefulSet or to your external host.
PGPASS=$(kubectl -n xpander get secret xpander-generated-keys -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d)
kubectl -n xpander exec supabase-db-0 -c postgres -- env PGPASSWORD="$PGPASS" \
  psql -h postgres -U xpander -d xpander -c '\dn'
kubectl -n xpander exec supabase-db-0 -c postgres -- env PGPASSWORD="$PGPASS" \
  psql -h postgres -U xpander -d xpander -c 'select execution_id, agent_id from xp_tiered.executions limit 5'
```

```bash theme={"dark"}
# Supabase's PostgreSQL, local to the same pod.
SBPASS=$(kubectl -n xpander get secret xpander-generated-keys -o jsonpath='{.data.SUPABASE_DB_PASSWORD}' | base64 -d)
kubectl -n xpander exec supabase-db-0 -c postgres -- env PGPASSWORD="$SBPASS" \
  psql -h 127.0.0.1 -U postgres -d postgres -c '\dt public.*'
```

```bash theme={"dark"}
# MongoDB, from inside mongodb-0, with the root credentials the chart generated.
kubectl -n xpander exec -it mongodb-0 -- mongosh -u <MONGO_ROOT_USER> -p <MONGO_ROOT_PASSWORD> --authenticationDatabase admin
```

At the `mongosh` prompt:

```javascript theme={"dark"}
db.getSiblingDB("monitoring").audit.find({}, { event_type: 1, timestamp: 1, user_id: 1 }).sort({ timestamp: -1 }).limit(10)
db.getSiblingDB("monitoring").cost_ledger.find().sort({ _id: -1 }).limit(3)
```

## Bringing your own PostgreSQL and Redis

Installer flags or values, with the passwords passed as `--set` so they never land in Git:

```bash theme={"dark"}
bash install.sh --edition airgap ... \
  --pg-mode external --pg-dsn 'postgresql://xpander:password@db.internal:5432/xpander' \
  --redis-mode external --redis-endpoint <clustercfg endpoint, no port> \
  --redis-tls --redis-cluster --redis-username <acl-user> --redis-password <pass>
```

```yaml theme={"dark"}
postgres:
  mode: external
  external:
    host: postgres.internal.acme.example
    port: 5432
redis:
  mode: external
global:
  redis:
    endpoint: <clustercfg endpoint, no port>
    clusterMode: true
    auth:
      username: <acl-user>
```

* **PostgreSQL**: create the role and database before the install. Keep `CREATEDB` on the role. Agent data lands as one schema per agent (`ag_<agent id>`) inside the `xpander` database. `keygen.overrides.POSTGRES_PASSWORD` is how xpander learns the password you set.

  ```sql theme={"dark"}
  CREATE ROLE xpander LOGIN PASSWORD '<password>' CREATEDB;
  CREATE DATABASE xpander OWNER xpander;
  ```

* **Valkey or MemoryDB**: the endpoint must ship the RediSearch commands, or knowledge bases accept writes and return nothing. On MemoryDB that is Valkey 7.3 on the parameter group with the search module.

* **Probes**: before installing, the installer launches a probe pod inside your namespace and runs `pg_isready` and `redis-cli ping` from where xpander will connect. A failed probe is a decision point, not an abort.

Details and the reference customer's RDS and MemoryDB sizes are on [Air-gapped: data tier](/self-hosted/airgap).

## MongoDB

MongoDB has no external mode. It holds the skill catalog's OpenAPI operations and the monitoring and audit stores, and runs in-cluster on every self-hosted deployment. Its volume is part of the chart's footprint; back it up with your cluster's volume snapshots.
