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 7091Bare-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 7091Prefer 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/docsgptHow 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.
| Setting | Effect | Requires |
|---|---|---|
AUTO_CREATE_DB | If the target database is missing, connects to the serverβs postgres maintenance DB and issues CREATE DATABASE. | CREATEDB privilege (or superuser) |
AUTO_MIGRATE | Runs alembic upgrade head against the target database. | Table-owner or superuser on the target DB |
AUTO_VECTOR_SCHEMA | With 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=falseRun 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.
| Install | Command |
|---|---|
docsgpt up --native or pip | docsgpt 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. |
| Kubernetes | The bundled postgres-init Job runs python -m docsgpt migrate --no-create; see Kubernetes. |
| Source checkout | python 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(orpython scripts/db/init_postgres.py) first. A real run also applies the migrations itself, the same way the app does on start (followingAUTO_CREATE_DB/AUTO_MIGRATE), but--dry-runchanges nothing, so against an empty database it fails withrelation "..." does not exist. - Name the Mongo database. The script reads the database
docsgpt, whatever databaseMONGO_URInames. If your data lives in another database, pass--mongo-db <name>. - Point it at the appβs storage (FAISS only). With
VECTOR_STORE=faiss, therename_faiss_indexesstep renamesindexes/<mongo_id>directories through the storage layer, rooted at the data home. Run the script with the sameDOCSGPT_HOME(or S3 settings) as the app. For the checkout Compose files, which keep indexes inapplication/indexes, that isDOCSGPT_HOME=$PWD/application, together withDOCSGPT_ENV_FILE=$PWD/.envso the checkoutβs.envis still read (DOCSGPT_HOMEalso moves where.envis 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,agentsThen 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 rundocsgpt migrate(python -m docsgpt migrateinside a container).permission denied to create databaseβ the role lacksCREATEDB. As superuser:ALTER ROLE <name> CREATEDB;. Or create the database manually and setAUTO_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=requiretoPOSTGRES_URI. ModuleNotFoundError: pymongoβpip install 'pymongo>=4.6'(only needed for the one-shot Mongo backfill).