Managed databases
Each app can provision one or more PostgreSQL databases. Paas runs them as
container instances on the same host as your apps, on the paas-apps
network, with a dedicated named volume for data.
Why this and not "just use the host's Postgres"?
- Per-app credentials, automatically generated and rotated on demand.
- Per-app data volume, so you can delete an app's data without hand-grepping.
- A clean separation from the control-plane Postgres (which stores Paas's own state) — they cannot accidentally share rows.
Provisioning
Dashboard → app → Managed databases → name main → Create.
The DatabaseProvisioner picks up the Provisioning row, runs:
docker run -d \
--name paas-db-<id> \
--network paas-apps \
-e POSTGRES_DB=app \
-e POSTGRES_USER=app \
-e POSTGRES_PASSWORD=<random> \
postgres:16-alpine
…records the IP / port / encrypted password, and flips the row to Ready.
Connection string
If the database is named exactly main, Paas auto-injects:
DATABASE_URL=postgres://app:<password>@<container-ip>:5432/app
Into your app's environment on the next deploy.
For other database names (or to retrieve the DSN manually), click Reveal DSN in the dashboard. This action is admin-only and audit-logged.
Connecting from your laptop (debugging)
The DB container is on paas-apps, which is internal-only. To psql it:
docker exec -it paas-db-<id> psql -U app -d app
Or temporarily expose its port:
docker run --rm -it --network paas-apps -e PGPASSWORD=<pw> \
postgres:16-alpine psql -h <db-ip> -U app app
Engine version
Defaults to 16. Pin a specific version when creating:
curl -X POST https://paas.example.com/api/orgs/acme/apps/web/databases/ \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"reporting","engineVersion":"15"}'
The container image is postgres:<engineVersion>-alpine.
Backups
Not in v1. You're responsible for pg_dumps on a schedule. A common
pattern is a small companion app that runs pg_dump from a CronJob and
ships the output to S3-compatible storage. v1.1 will add scheduled backups
to a configurable destination.
Deletion
Dashboard → Managed databases → click delete (owner-only). By default the volume is preserved so you can roll back. To also delete the data:
curl -X DELETE \
"https://paas.example.com/api/orgs/acme/apps/web/databases/<id>?deleteVolume=true" \
-H "Authorization: Bearer $TOKEN"
(There's no UI button for the destructive variant on purpose.)