Provisioning
Open your project’s Database tab and provision. You get a dedicated database and role, and the DSN is injected into your app as DATABASE_URL on the next deploy. The full connection details (host, port, user, password) stay visible on the tab for external tools. Database size is capped per plan (see the limits).
import pg from 'pg';
// DATABASE_URL is injected automatically once a database is provisioned.
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
const { rows } = await pool.query('SELECT now()');Postgres version
When you provision, choose Postgres 17 (the default) or Postgres 18. The Database tab shows the exact running version — for example, 17.9 — not just the major line. An existing database stays on the version it was created with; nothing changes unless you choose.
To move an existing database to a different version, dump it and restore into a freshly provisioned one (pg_dump from the old, pg_restore into the new). Your DATABASE_URL is re-injected on the next deploy.
Migrations and seeds
Run migrations the same way you would anywhere: as part of your build script (prisma migrate deploy, drizzle-kit push, knex migrate:latest) or from your app on boot. The database is reachable during builds, so build-time migrations work.
Connecting from outside
The connection details on the Database tab work from external clients (psql, TablePlus, your ORM’s studio). Data stays on Canadian infrastructure — the same sovereignty posture as your app.
Analytics on your data
Project databases show up as a source in Data Workshop: browse tables and run SQL from the dashboard. To read or write your database on a schedule — nightly rollups, reconciliation, cross-project moves — use scheduled SQL queries.
Backups
Platform databases are backed up nightly. For belt-and-suspenders on critical data, pg_dump with your connection string works from anywhere.