#Database
Every CoDuck project comes with its own private Postgres database. It's provisioned automatically on first deploy, and the connection string is injected into your container as DATABASE_URL (pooled) and DIRECT_URL (direct, for migrations).
[!IMPORTANT] The database is provisioned empty — CoDuck creates the database, not your tables. You must create your schema yourself on deploy (see below). An app that assumes tables already exist will fail with
relation "…" does not exist.
#How it works
On first deploy, CoDuck:
- Creates a Postgres database dedicated to your project.
- Provisions a dedicated database user with permissions scoped to that DB only.
- Injects
DATABASE_URL(PgBouncer at127.0.0.1:6432on the VPS loopback, transaction-pool mode withmax_prepared_statements=100) andDIRECT_URL(postgres directly at127.0.0.1:5433, used only by Prisma's schema engine forprisma db push/prisma migrate deploy) — both reserved; you can't override them. See Runtime architecture for the full container + networking model.
Subsequent deploys reuse the same database. Your app reads process.env.DATABASE_URL like any normal Postgres host — Prisma, Drizzle, Kysely, node-postgres, pg, knex, and sequelize all work against it. The CoDuck Auth SDK (@coduckai/sdk/auth) uses the same database to store users.
#Schema and migrations
How CoDuck applies your schema depends on whether you use Prisma and whether you've set a preStart:
- Prisma, no
preStart— ifprisma/schema.prismadeclaresmodels, CoDuck runsprisma db pushon each deploy to sync the schema (additive; it preserves tables it doesn't know about). This is the zero-config path. - You set a
preStart— CoDuck does not auto-push; yourpreStartowns schema setup. Use this for real migration files:"preStart": "prisma migrate deploy". - Not using Prisma — set a
preStartthat runs your migration tool, e.g."preStart": "drizzle-kit push"or"preStart": "node scripts/migrate.js".
preStart runs after install + build, before the app starts, on every deploy — see
the coduck.json reference. For migrations, prefer
DIRECT_URL over DATABASE_URL (Prisma's schema engine doesn't go through PgBouncer).
#Inspect your data
Open your project at https://app.coduck.ai/project/<projectId>, switch to the Cloud panel, then the Data tab. You'll see your schema, every table, and recent rows. The view is read-only — to write data, use your application code.
#Backups
Backups run automatically every night (cluster-level physical backups via pgBackRest, managed by CoDuck). You can also create one on demand from the Cloud panel → Data tab, in the Backups section. On-demand backups use pg_dump so you get a portable SQL export of just your project's database. Restoring is destructive and asks for confirmation before overwriting your current DB.
#Why there's no raw connection URL
#Connection pooling
PgBouncer handles connection pooling on the server side, so a single project doesn't need a large client-side pool. Inside your app, set your client's max_connections to 10 or lower. Opening too many direct connections will get throttled.
#Limits
| Resource | Limit |
|---|---|
| Storage | 1 GB per project DB (soft; raisable on paid plans) |
| Connections | PgBouncer-pooled; keep app pool ≤ 10 |
| Compute | Shared with the cluster; no separate DB CPU billing |
#Common failures
relation "…" does not existat runtime. The database starts empty and your schema never got created. Make sure a Prisma schema with models is present (CoDuck runsprisma db push), or set apreStartthat runs your migrations.- Migration/
db pushfails on deploy. Check the deploy logs. A destructive change (dropping a column with data) is blocked byprisma db pushwithout--accept-data-loss; switch to a real migration (preStart: "prisma migrate deploy"). bouncer config erroron every query. PgBouncer can't authenticate connections to your DB. Almost always caused by runningDROP SCHEMA public CASCADE(or equivalent) from your app, which destroys thepublic.user_lookup()function PgBouncer needs and theUSAGEgrant topgbouncer_auth. Contact support to restore them. To migrate, drop and recreate your own tables instead of nukingpublic.- Connection pool exhausted. Symptom is
too many clientsor hung requests under load. Lowermax_connectionsin your client pool — PgBouncer is already pooling on the server side, so your app should open very few direct connections. - Schema mismatch at runtime. Your code expects a column the DB doesn't have — a migration wasn't applied. CoDuck auto-runs
prisma generatewhen your schema has models, so you don't need it in your build step; the usual cause is an uncommitted schema change.
#For developers
If you'd rather work from a terminal, the CoDuck CLI exposes read-only schema/table inspection and backup management for your project. See CLI commands.
#Next
- Deploying — when migrations run, deploy lifecycle.
- Sending email — the other auto-provisioned service.