
Migrating from Prisma v5 to v7 (Without Breaking Production)
A practical migration guide from Prisma v5 to v7 — what breaks, how to fix it, and what performance changes to expect.
Prisma v7 is not just a version bump. It changes how datasource URLs are configured, how Prisma Client is generated, and how the client connects to your database at runtime.
In this guide, I'll cover a practical migration path from Prisma v5 to v7, what breaks, how to fix it, and what performance changes to expect.
Before you start
Prerequisites — check these before touching any code:
- Node.js ≥ 18.18 (Prisma v7 drops older LTS lines). Use
node -vto confirm.- TypeScript ≥ 5.1 recommended. Older versions may cause type-recursion issues with the new generated client.
- MongoDB users — Prisma v7 does not support MongoDB yet. Stay on v6 until official support lands.
- Package manager —
npm,pnpm, andyarnall work, but make sure lockfiles are committed before you start upgrading.
Common terms used in this guide
- Prisma Client: The generated type-safe database client your app imports.
- Driver Adapter: The DB driver bridge Prisma v7 now requires (for example
@prisma/adapter-pg). - prisma.config.ts: New config entry point where datasource URLs now belong.
- Generated Output Path: Where Prisma client files are generated (no longer defaulting to
node_moduleswith new generator).
1. Why move to v7?
- Better architecture for modern runtimes.
- Smaller deployment footprint (especially with the new client path).
- Cleaner separation between schema and environment config.
- Future-proofing:
prisma-client-jsis legacy direction;prisma-clientis the forward path.
2. Breaking changes you must handle
2.1 Datasource URL is no longer in schema.prisma
Before (v5 style):
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}After (v7 style):
datasource db {
provider = "postgresql"
}And move URL config to prisma.config.ts:
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
datasource: {
url: env("DATABASE_URL"),
},
});Which URL variable? Most apps use
DATABASE_URLfor the main runtime connection andDIRECT_URL(or a shadow-database URL) specifically for migrations. Inprisma.config.ts, set theurlto whatever your app uses at runtime — typicallyDATABASE_URL. If you run migrations through a separate direct connection, configure that in your migration scripts or CI, not here.
2.2 Generator changes (prisma-client-js → prisma-client)
Before:
generator client {
provider = "prisma-client-js"
}After:
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}Now imports must come from generated path, not @prisma/client:
// before
import { PrismaClient } from "@prisma/client";
// after
import { PrismaClient } from "../generated/prisma/client";2.3 Driver adapter is required at runtime
For PostgreSQL:
npm i @prisma/adapter-pg pgimport { PrismaClient } from "../generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const adapter = new PrismaPg(pool);
export const prisma = new PrismaClient({ adapter });2.4 Platform requirements increased
Make sure your runtime/toolchain is compatible — Node ≥ 18.18 and TypeScript ≥ 5.1 are expected. Check the Prisma system requirements page for the latest specifics.
2.5 Also changed in v7
These won't block the core migration, but they will bite you later if you ignore them:
- Middleware removed — If you use
prisma.$use(), it no longer exists. Replace middleware with client extensions ($extends), which offer the same hook points with better type safety. - Auto-seeding removed —
prisma migrate devandprisma migrate resetno longer run your seed script automatically. Runprisma db seedexplicitly after migrations.
2.6 ESM and module format
Prisma v7's new generator and prisma.config.ts lean towards ESM conventions. If your project is heavily CommonJS, plan the module-format changes early — you may need to adjust tsconfig.json ("module", "moduleResolution") and potentially add "type": "module" in package.json or use .mts extensions. Check Prisma's docs for ESM-specific guidance before you start rewriting imports.
3. Migration flow (safe order)
- Upgrade packages (
prisma, client package, adapter/driver). - Move datasource URL config into
prisma.config.ts. - Update generator to
prisma-clientwith output. - Regenerate client (
prisma generate). - Rewrite imports to generated client path.
- Update Prisma bootstrap to use adapter.
- Run:
prisma validate
prisma db pull # or prisma migrate ... as needed
tsc --noEmit
# full build + smoke test4. Performance expectations after migration
What usually improves:
- Startup/deploy ergonomics.
- Better control over runtime driver behavior.
- Leaner generated-client usage pattern.
What to watch carefully:
- Connection pooling behavior is now from your DB driver (
pg, etc.), not old Prisma defaults. - Query performance can improve, but measure before/after with your own workloads.
- If you see new timeout behavior, tune pool options explicitly.
5. Common migration errors and fixes
Argument "url" is missing in datasource
Means Prisma config isn't being resolved by editor/CLI.
Fix prisma.config.ts env loading and restart Prisma language server.
PrismaClient ... requires adapter or accelerateUrl
You created client without adapter in v7 architecture.
Pass adapter in new PrismaClient({ adapter }).
Build crash / TypeScript recursion after upgrade
- Simplify overly deep Prisma generic types.
- Remove old runtime-library type imports.
6. CI/CD changes you should have
In pipeline before build/deploy:
npm ci
npm run prisma:pull:prod
npm run prisma:generate:prod
npm run buildIf generated client folder is not committed, CI must always generate it.
Rollback plan
Before you cut over to production, have a way back:
- Keep a branch pinned to Prisma v5 with the old schema and client setup. If something goes wrong, you can revert package versions and redeploy from this branch within minutes.
- Don't delete the old generated client path until your CI is fully green and production has been stable for at least a few days.
- Lockfile discipline — commit your lockfile before the upgrade so a
git reverton the version bump actually restores the exact dependency tree.
This matches the "config first, validate aggressively" approach — you want the safety net in place before you need it.
Checklist
Low Priority
- Standardize one Prisma bootstrap file for whole app.
- Remove legacy
@prisma/clientimports once generated-path migration is done. - Keep docs for team onboarding updated.
Medium Priority
- Add migration smoke tests for critical queries.
- Benchmark key APIs before/after migration.
- Tune DB pool settings for production traffic.
High Priority
- Ensure
prisma.config.tsis correct and env-resolvable in local + CI. - Ensure adapter-based client init is used everywhere.
- Block deploy if
prisma validateortsc --noEmitfails. - Confirm rollback plan before production cutover.
7. Benefits we saw after migration
After completing the migration across our product codebase, here's what actually changed:
- Smaller deploy size — the new
prisma-clientgenerator produces a leaner output compared to the oldprisma-client-js. Our deploy artifact dropped noticeably. - Faster cold starts — deploy artifacts often shrink and cold starts can improve because the new client generation model changes what gets packaged and how connections are handled. Serverless and edge deployments benefit the most.
- Full control over connection pooling — with the driver adapter (
pgPool), we now own the pool config entirely. No more guessing what Prisma's internal pool is doing. We tunedmax,idleTimeoutMillis, andconnectionTimeoutMillisto match our traffic patterns. - Cleaner separation of concerns — moving the datasource URL out of
schema.prismaintoprisma.config.tsmeans the schema is truly environment-agnostic. No moreenv("DATABASE_URL")scattered in schema files. - Simpler debugging — since the runtime driver is now a standard
pgPool, we can attach listeners, log queries, and inspect connections the same way we would in any Node.js app — no Prisma-specific workarounds. - Future-proof architecture — the
prisma-clientgenerator is the forward path. Staying onprisma-client-jsmeans you'll eventually hit a dead end when new features only land in the new generator.
Prisma v7 migration is very manageable once you treat it as an architecture shift, not just a package upgrade. Do config first, client generation second, runtime adapter third, then validate aggressively.
