backend
Prisma, and catching schema drift before it catches you
Prisma, and catching schema drift before it catches you
schema.prisma is the single source of truth for the database shape — models, relations, indexes, enums in one file — and Prisma generates a typed client and manages migrations from it.
prisma migrate dev # dev: edit the schema, get + apply a migration
prisma migrate deploy # prod/CI: apply existing migrations only
prisma generate # regenerate the typed client
prisma migrate diff # compare two schema states — drift detection
const app = await prisma.applications.findUnique({
where: { id },
include: { children: true, programs: true },
});
Schema drift is the failure mode that got me
The database no longer matches what schema.prisma says — because someone edited the schema and forgot to generate the migration, or made a manual change directly. It fails silently at first; local dev still works. Then it surfaces later, usually in production, as a confusing error or the wrong data shape somewhere unrelated.
The fix that actually works: make CI verify migrations reproduce the schema on every run.
prisma migrate diff --from-config-datasource --to-schema database/schema.prisma --exit-code
If the applied migrations don't exactly reconstruct the schema file, CI fails immediately — before drift reaches staging.
A few practical things I hit:
- I keep the schema at
Backend/database/schema.prismawithprisma.config.tspointing there, not the defaultprisma/schema.prisma. Fully supported, worth writing down clearly because every tutorial assumes the default. - With pgBouncer in front, Prisma needs the pooled URL for runtime and the direct URL for migrations, because transaction pooling doesn't support the session-level features DDL needs.
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuidkeeps UUID generation consistent for rows inserted outside Prisma — raw SQL, seed scripts, another service.
One thing I noticed reconstructing this project's real history: every migration file is effectively a dated commit message for the database. Migration names describe what changed rather than being wrapped in a feature narrative, so reading the migrations folder chronologically is often more precise than the git log.