Database & Prisma

The Prisma workflow, and how to swap PostgreSQL for another database.


PostgreSQL is the default: DATABASE_URL, prisma/schema.prisma, the @prisma/adapter-pg adapter, and Better Auth's postgresql provider all agree on it out of the box. Prisma itself can target any database it supports, so switching is a config change, not a rewrite.

Everyday commands

CommandWhat it does
pnpm db:generateRegenerates the Prisma client into src/generated/prisma
pnpm db:migrateCreates and applies a migration locally (prisma migrate dev)
pnpm db:deployApplies committed migrations (prisma migrate deploy) — safe for production
pnpm db:pushPushes the schema without a migration — throwaway prototyping only
pnpm db:studioOpens Prisma Studio
pnpm auth:generateRegenerates the Better Auth Prisma models

Don't use db:push or migrate dev against production. db push has no migration history and can drop data; migrate dev is a local development command. Production always uses migrate deploy — that's what pnpm db:deploy and pnpm start run.

Switching databases

  1. Change provider in prisma/schema.prisma and DATABASE_URL in .env.
  2. Install the matching Prisma adapter — for example @prisma/adapter-mariadb or @prisma/adapter-better-sqlite3 — and wire it in src/api/lib/prisma.ts.
  3. Set the same engine on Better Auth in src/api/lib/auth.ts:
src/api/lib/auth.ts
prismaAdapter(prisma, {
  provider: 'mysql', // or 'sqlite', 'sqlserver', 'mongodb', ...
});
  1. Run pnpm db:generate and pnpm db:migrate (or pnpm db:deploy against an empty database).

Prisma supports MySQL, SQLite, SQL Server, CockroachDB, MongoDB, and more — the same three-file change (schema provider, adapter, Better Auth provider) applies to each.

Recovering from a db:push'd database

If a database already has the tables — for example because you previously ran db:push — don't re-run the init migration's SQL. Mark it as applied instead, then deploy normally:

Terminal
pnpm exec prisma migrate resolve --applied 20260902120000_init
pnpm db:deploy

Schema layout

The schema is split by domain and composed together:

prisma/
prisma/
├── schema.prisma
├── models/
│   ├── auth.prisma   # Better Auth tables
│   └── task.prisma   # Task model
└── migrations/        # committed SQL, applied with db:deploy