Documentation / Exploitation / Guides pratiques / Use Postgres for the run index

Use Postgres for the run index

The proxy keeps a lookup index of runs (id, workflow, patient, event, creation date, terminal status) in a small database, selected by the RUN_DB_URL environment variable. By default this is a local SQLite file, which only works for a single proxy instance. Switch to Postgres when you run more than one proxy replica, so every replica reads and writes the same index. See reference/run-store.md for what the index contains and why it exists separately from Restate's durable state, and explanation/sizing.md for when horizontal scaling of the proxy is worth doing in the first place.

Before you start

  • Only the proxy process reads RUN_DB_URL — the endpoint never touches the run index (see reference/environment-variables.md). You do not need to change anything on the endpoint.
  • Losing or rebuilding this index never loses a run: the authoritative state (journal, suspension, resumption) lives in Restate, not here. See explanation/why-durable-execution.md.
  • The schema (a single runs table) is created automatically on boot — there is no migration script to run by hand, and nothing to provision beyond a reachable database.

1. Provision a Postgres database

Local stack (docker compose)

Postgres is already running: it has no compose profile, because the definition store requires it (see Manage workflow storage). So docker compose up -d, with or without the stack profile, already started it:

docker compose --profile stack up -d --build

That is the postgres service (postgres:17-alpine, database clinical, user clinical) defined in docker-compose.yml, persisted in the pg-data volume and published on host port 5433 (POSTGRES_PORT) so it cannot collide with another Postgres on the machine. The default password is clinical; override it for anything beyond a throwaway local stack:

POSTGRES_PASSWORD=change-me docker compose --profile stack up -d --build

Pointing the run index at that same database is then just a matter of RUN_DB_URL — the definition tables and runs are disjoint.

External / production Postgres

Provision a reachable Postgres instance (managed service or self-hosted) and create an empty database plus a role with rights to create tables in it — no further setup is required, the proxy issues its own CREATE TABLE IF NOT EXISTS and ALTER TABLE ... ADD COLUMN IF NOT EXISTS on first connection (apps/api/src/server/run-store.ts). As with any credential, keep the connection string out of the versioned instance manifest and inject it through the environment (secret store, Kubernetes Secret, compose .env).

2. Point the proxy at it

Set RUN_DB_URL to a postgres:// (or postgresql://) connection string for the proxy process:

RUN_DB_URL=postgres://clinical:clinical@postgres:5432/clinical \
  docker compose --profile stack up -d --build

For a proxy running outside compose (bare process or another orchestrator), export the same variable before starting it:

export RUN_DB_URL=postgres://<user>:<password>@<host>:5432/<database>
pnpm --filter @meridian/api run server

Any URL starting with postgres:// or postgresql:// selects the Postgres backend; anything else must start with sqlite: or the proxy refuses to boot with an "unrecognized RUN_DB_URL" error. There is no partial/hybrid mode — one proxy deployment uses exactly one backend at a time.

3. Restart the proxy

Restart every proxy replica with the new RUN_DB_URL so they all point at the same Postgres database — this is the property that makes multiple replicas safe (SQLite is a local file per replica; Postgres is shared). Restarting the proxy is enough; you do not need to restart the endpoint or Restate. See how-to/upgrade-the-platform.md for the general proxy restart/rollout order.

4. Verify

Check that the proxy reports the run index as reachable:

curl http://localhost:4000/readyz

/readyz returns 200 only if both the Restate ingress and the run index respond; on failure it returns 503 with a { checks } detail telling you which one failed. Then confirm the index is actually being written to by starting a run and listing it back through GET /api/runs, or by inspecting the table directly:

psql "$RUN_DB_URL" -c 'select id, workflow_name, created_at from runs order by created_at desc limit 5;'

Notes on switching

  • Switching backends does not migrate existing data: pointing RUN_DB_URL at a fresh Postgres database starts with an empty runs table. If you need to keep the run history visible, back up the old SQLite file first — see how-to/back-up-and-restore.md — there is no built-in SQLite-to-Postgres migration tool.
  • Back up Postgres the same way as any other database in your stack (pg_dump); this index is convenience data, not the source of truth, so an occasional dump is enough (again, how-to/back-up-and-restore.md).
75 documents8 sectionssource : /docs · généré au build