Skip to content
PaloNexus
Request access Request

Migrations

PaloNexus’s persistent state lives in three places, and all three create their own schema idempotently — there is no separate migration tool to run, and a re-apply is safe. This page documents what gets created and how to operate it. See Persistence for choosing a backend.

OwnerBackend selected bySchema creation
Control-plane registryREGISTRY_BACKEND + REGISTRY_DB_URLone document table created on startup (CREATE TABLE IF NOT EXISTS)
agent-idp storeIDP_STORE_BACKEND + IDP_DB_URLper-feature tables created on first use (CREATE TABLE IF NOT EXISTS)
LangGraph checkpointer (per agent)PALONEXUS_AGENT_DB_URLAsyncPostgresSaver.setup() creates its own tables on entry

A single JSON-document table keyed by service name. The table/database names are overridable with REGISTRY_DB_TABLE and REGISTRY_DB_DATABASE. One SQL implementation serves Postgres / MySQL / SQLite (dialect-aware upsert); MongoDB uses a document collection.

Terminal window
REGISTRY_BACKEND=postgres \
REGISTRY_DB_URL='postgres://palonexus:pw@pg-rw.palonexus.svc:5432/palonexus?sslmode=disable'
# On boot: CREATE TABLE IF NOT EXISTS <REGISTRY_DB_TABLE|registry_services> (...)

The store and the enterprise identity-and-access-management (IAM) features create these tables automatically on first use (no migration step):

agents governed agent records (provisioning, owner/sponsor)
delegations task-scoped delegation grants + status
revocations revoked JTIs / StatusList state
idp_employees directory employees (F1)
idp_groups directory groups (F1)
idp_syncs per-sync reconcile reports (F1)
idp_agent_governance agent ownership/governance records (F3)
idp_gov_delegations authorized governance delegations (F4/F5)
idp_revocations_log durable revocation log with reason codes (F4)
idp_tokens STS token audit log — metadata only (F6)
Terminal window
IDP_STORE_BACKEND=postgres \
IDP_DB_URL='postgresql://palonexus:pw@pg-rw.agent-idp.svc:5432/agentidp'

Agents that need durable threads + human-in-the-loop (HITL) pause/resume use AsyncPostgresSaver. On startup the agent calls await checkpointer.setup(), which creates LangGraph’s checkpoint tables (checkpoints, checkpoint_writes, checkpoint_blobs, …). With no DB URL the agent falls back to a non-durable MemorySaver.

Terminal window
PALONEXUS_AGENT_DB_URL='postgresql://palonexus:pw@pg-rw.agent-idp.svc:5432/agentidp'
# AsyncPostgresSaver.from_conn_string(...).setup() — creates the checkpoint tables

Because every schema uses CREATE TABLE IF NOT EXISTS / setup(), restarting or redeploying re-runs creation harmlessly — existing data is preserved, missing tables are added. There is no “migrate up/down” command and no version table to babysit for the MVP schema.

The deploy/kustomize/components/postgres/ component provisions a CloudNativePG (CNPG) Cluster per component (palonexus, agent-idp) and wires each data source name (DSN) in from the generated *-app secret — no databases are created or passwords written by hand:

deploy/kustomize/overlays/selfhost/kustomization.yaml
components:
- ../../components/postgres # requires the CNPG operator installed first

The apps point REGISTRY_DB_URL / IDP_DB_URL at the *-rw Service; tables are created on their first boot against it.

Changing *_BACKEND does not copy data — the new backend starts empty. To move from memory or SQLite to Postgres without losing state:

  1. Quiesce writes — scale the writer (control-plane / agent-idp) to read-only or pause registrations/approvals.
  2. Export the current store. For the registry, re-POST services from the source of truth (registrations are declarative); for agent-idp, dump and re-insert the JSON documents, or replay provisioning + delegations.
  3. Re-point *_DB_URL at Postgres and restart — tables are created on boot.
  4. Verify — list services (GET /v1/registry/services), check agent provisioning, and run pn.audit.verify_chain().

Because registrations and provisioning are declarative and re-runnable, the simplest “migration” is often just to re-seed against the new backend.

If a durable backend is misconfigured or unreachable at startup, the process exits rather than silently dropping to in-memory — a DSN typo must never quietly lose every registration. This is the same fail-closed posture as the security model.

  • Persistence — backends and the postgres component.
  • Backups — backing up and restoring these schemas.
  • Upgrades — handling schema changes across versions.