Skip to Content
Deploy & Operate🐘 PostgreSQL for User Data

PostgreSQL for User Data

DocsGPT stores conversations, agents, prompts, sources, attachments, workflows, logs, and token usage in PostgreSQL. MongoDB is no longer required.

ℹ️

Vector stores are independent β€” VECTOR_STORE can still be pgvector, faiss, qdrant, milvus, elasticsearch, or mongodb.

Quickstart

Three common paths. Each assumes Postgres 13+ and the default env vars AUTO_MIGRATE=true / AUTO_CREATE_DB=true (both ship enabled).

Docker Compose

Every bundled Compose file ships a postgres service. App boot handles the rest β€” no sidecar, no init job. From the repository root:

docker compose --env-file .env -f deployment/docker-compose-hub.yaml up -d

--env-file .env makes Compose read the root .env for the ${...} values in the file (such as DOCSGPT_IMAGE_TAG); without it they fall back to their defaults. docsgpt up and the standalone file work the same way; see Docker Deployment.

Managed Postgres (Neon, RDS, Supabase, Cloud SQL)

Point POSTGRES_URI at the provider-given URI. The app applies the schema on first boot.

export POSTGRES_URI="postgresql://user:pass@host/docsgpt?sslmode=require" uvicorn docsgpt.asgi:asgi_app --host 0.0.0.0 --port 7091

Bare-metal Postgres

Run Postgres locally and point POSTGRES_URI at the default superuser. First boot creates both the database and the schema.

export POSTGRES_URI="postgresql://postgres@localhost/docsgpt" uvicorn docsgpt.asgi:asgi_app --host 0.0.0.0 --port 7091

Prefer a dedicated non-superuser role? Create it once as superuser β€” the app never creates roles.

CREATE ROLE docsgpt LOGIN PASSWORD 'docsgpt' CREATEDB; -- Then: POSTGRES_URI=postgresql://docsgpt:docsgpt@localhost/docsgpt

How auto-bootstrap works

Three env vars control startup behavior. All default to true and are idempotent. They run when the API or the worker starts.

SettingEffectRequires
AUTO_CREATE_DBIf the target database is missing, connects to the server’s postgres maintenance DB and issues CREATE DATABASE.CREATEDB privilege (or superuser)
AUTO_MIGRATERuns alembic upgrade head against the target database.Table-owner or superuser on the target DB
AUTO_VECTOR_SCHEMAWith VECTOR_STORE=pgvector, creates the documents table (and the graph tables when GraphRAG is on) and checks its embedding width. No Alembic migration covers the vector database, because it can be a separate cluster.CREATE on the vector database; the vector extension installed or creatable

Concurrent workers serialize through alembic_version, so rolling restarts are safe. If the role lacks the required privilege, startup fails fast with a clear error rather than silently skipping.

ℹ️

Convenient in dev. In production, disable both and run migrations as an explicit step β€” see Production hardening.

Production hardening

Set the flags to false in prod and run migrations as a gated, auditable step before rolling out the app.

AUTO_MIGRATE=false AUTO_CREATE_DB=false AUTO_VECTOR_SCHEMA=false

Run migrations from your CI/CD pipeline, a Kubernetes Job, or an init-container ahead of the app rollout. docsgpt migrate is the supported command; add --no-create when the database is created for DocsGPT, so a typo in POSTGRES_URI fails instead of creating a new one.

InstallCommand
docsgpt up --native or pipdocsgpt migrate --no-create
Checkout Compose (from the repository root)docker compose --env-file .env -f deployment/<file>.yaml run --rm backend python -m docsgpt migrate --no-create
Installer or docsgpt up on Docker (the default), from the stack directory (~/.docsgpt/server by default)docker compose run --rm backend python -m docsgpt migrate --no-create. The host’s docsgpt migrate can’t reach this stack’s database.
KubernetesThe bundled postgres-init Job runs python -m docsgpt migrate --no-create; see Kubernetes.
Source checkoutpython scripts/db/init_postgres.py or alembic -c docsgpt/alembic.ini upgrade head

The Docker image has no docsgpt console script, so containers call it as python -m docsgpt. Images up to 0.21.0 lack that entry point too; use python -m docsgpt.cli migrate --no-create there.

AUTO_VECTOR_SCHEMA=false only matters with VECTOR_STORE=pgvector. It stops the boot-time vector DDL and width check, but the pgvector store still creates its table on the first write if it is missing. If the runtime role has no DDL rights, create the vector tables once beforehand, for example by starting the app once with a privileged role.

The reasoning: the app’s runtime role shouldn’t carry DDL privileges, migrations should gate each rollout, and an explicit step is auditable β€” implicit first-boot bootstrap is fine for dev but muddies prod deploys.

⚠️

Migrations are not reversible by the app. Always back up production Postgres before running alembic upgrade head on a new release.

Migrating from MongoDB

One-shot, offline, app stopped. The copy runs from a source checkout: scripts/db/backfill.py is not in the Docker image or the pip package.

Before you run it

  • Check out the release you are moving to and install its requirements plus pymongo, as below.
  • Prepare the Postgres schema. Run docsgpt migrate (or python scripts/db/init_postgres.py) first. A real run also applies the migrations itself, the same way the app does on start (following AUTO_CREATE_DB / AUTO_MIGRATE), but --dry-run changes nothing, so against an empty database it fails with relation "..." does not exist.
  • Name the Mongo database. The script reads the database docsgpt, whatever database MONGO_URI names. If your data lives in another database, pass --mongo-db <name>.
  • Point it at the app’s storage (FAISS only). With VECTOR_STORE=faiss, the rename_faiss_indexes step renames indexes/<mongo_id> directories through the storage layer, rooted at the data home. Run the script with the same DOCSGPT_HOME (or S3 settings) as the app. For the checkout Compose files, which keep indexes in application/indexes, that is DOCSGPT_HOME=$PWD/application, together with DOCSGPT_ENV_FILE=$PWD/.env so the checkout’s .env is still read (DOCSGPT_HOME also moves where .env is looked up). If the rename misses them, retrieval returns nothing, without an error.

Run the copy

pip install -r docsgpt/requirements.txt pip install 'pymongo>=4.6' export POSTGRES_URI="postgresql://docsgpt:docsgpt@localhost:5432/docsgpt" export MONGO_URI="mongodb://user:pass@host:27017/docsgpt" python -m docsgpt migrate # create the schema python scripts/db/backfill.py --dry-run # preview python scripts/db/backfill.py # real run # or: python scripts/db/backfill.py --tables users,agents

Then unset MONGO_URI and start the backend β€” nothing consults Mongo in the default path anymore. The backfill is idempotent (per-table ON CONFLICT upserts, event-log tables deduped via mongo_id), so re-running is safe and re-syncs any drifted rows. Keep Mongo online until you’ve verified Postgres is complete; decommission afterwards unless you still use it as a vector store.

⚠️

No dual-write window and no runtime flag β€” on the current version, Postgres is the only user-data store the backend reads or writes.

Troubleshooting

  • relation "..." does not exist β€” schema not applied. Either let the app bootstrap it (AUTO_MIGRATE=true) or run docsgpt migrate (python -m docsgpt migrate inside a container).
  • permission denied to create database β€” the role lacks CREATEDB. As superuser: ALTER ROLE <name> CREATEDB;. Or create the database manually and set AUTO_CREATE_DB=false.
  • role "docsgpt" does not exist β€” roles are never auto-created. As superuser: CREATE ROLE docsgpt LOGIN PASSWORD '...';.
  • SSL errors on a managed provider β€” append ?sslmode=require to POSTGRES_URI.
  • ModuleNotFoundError: pymongo β€” pip install 'pymongo>=4.6' (only needed for the one-shot Mongo backfill).
Last updated on