Upgrade to Prisma ORM 7

Verified 中级 Intermediate 流程型 Process ⚡ Claude Code 专属 ⚡ Claude Code Optimized
6 min read · 275 lines

Prisma official v7 upgrade guide: breaking changes + step-by-step migration + ESM + framework adaptation

Upgrade to Prisma ORM 7

Overview

Complete guide for migrating from Prisma ORM v6 to v7. This upgrade introduces significant breaking changes: ESM-only, required driver adapters, and a new configuration system.

Important Notes

  • MongoDB not yet supported in v7 - continue using v6
  • Node.js 20.19.0+ required
  • TypeScript 5.4.0+ required

Breaking Changes Summary

Change v6 v7
Module format CommonJS ESM only
Generator provider prisma-client-js prisma-client
Output path Auto (node_modules) Required explicit
Driver adapters Optional Required
Config file .env + schema prisma.config.ts
Env loading Automatic Manual (dotenv)
Middleware $use() Client Extensions
Metrics Preview feature Removed

Quick Upgrade Commands

npm install @prisma/client@7
npm install -D prisma@7
npm install @prisma/adapter-pg    # PostgreSQL example
npm install dotenv
npx prisma generate

Step-by-Step Migration

1. Configure ESM

package.json:

{ "type": "module" }

tsconfig.json:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
    "target": "ES2023",
    "strict": true,
    "esModuleInterop": true
  }
}

Alternative: "module": "Node16" with "moduleResolution": "Node16" (requires .js extensions on imports).

2. Update Schema

// v6
generator client {
  provider = "prisma-client-js"
}

// v7
generator client {
  provider = "prisma-client"
  output   = "../generated"
}

Key changes:

  • output is now required
  • engineType removed
  • URLs move to prisma.config.ts, keep only provider in datasource block

3. Create prisma.config.ts

import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: { path: 'prisma/migrations' },
  datasource: {
    url: env('DATABASE_URL'),
    directUrl: env('DIRECT_URL'),
    shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
  },
})

4. Install Driver Adapter

# PostgreSQL
npm install @prisma/adapter-pg

# MySQL
npm install @prisma/adapter-mariadb mariadb

# SQLite
npm install @prisma/adapter-better-sqlite3

# Prisma Postgres
npm install @prisma/adapter-ppg @prisma/ppg

5. Update Client Instantiation

// v6
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

// v7
import { PrismaClient } from '../generated/client'
import { PrismaPg } from '@prisma/adapter-pg'

const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL })
const prisma = new PrismaClient({ adapter })

6. Generate and Test

npx prisma generate
npx prisma migrate dev  # if needed

Migrating Removed Features

Middleware to Client Extensions

// v6 middleware (removed)
prisma.$use(async (params, next) => {
  const result = await next(params)
  return result
})

// v7 client extensions
const prisma = new PrismaClient({ adapter }).$extends({
  query: {
    $allModels: {
      async $allOperations({ operation, model, args, query }) {
        const before = Date.now()
        const result = await query(args)
        console.log(`${model}.${operation} took ${Date.now() - before}ms`)
        return result
      },
    },
  },
})

Soft Delete Pattern

const prisma = new PrismaClient({ adapter }).$extends({
  query: {
    user: {
      async delete({ args, query }) {
        return prisma.user.update({
          where: args.where,
          data: { deletedAt: new Date() },
        })
      },
      async findMany({ args, query }) {
        args.where = { ...args.where, deletedAt: null }
        return query(args)
      },
    },
  },
})

Metrics Replacement

let totalQueries = 0
const prisma = new PrismaClient({ adapter }).$extends({
  client: { async $totalQueries() { return totalQueries } },
  query: {
    $allModels: {
      async $allOperations({ query, args }) {
        totalQueries += 1
        return query(args)
      },
    },
  },
})

rejectOnNotFound to OrThrow

// v6 (removed)
const prisma = new PrismaClient({ rejectOnNotFound: true })

// v7
const user = await prisma.user.findUniqueOrThrow({ where: { id: 1 } })
const user = await prisma.user.findFirstOrThrow({ where: { email: 'test@example.com' } })

Removed CLI Flags

Removed Migration
--skip-generate (migrate dev, db push) Run prisma generate explicitly
--skip-seed (migrate dev, migrate reset) Run prisma db seed explicitly
--schema, --url (db execute) Configure in prisma.config.ts
--from-url, --to-url (migrate diff) Use --from-config-datasource / --to-config-datasource

Framework Considerations

Next.js

Rename next.config.js to next.config.mjs:

export default { /* config */ }

Jest

Configure for ESM or switch to Vitest (native ESM):

{
  "jest": {
    "preset": "ts-jest/presets/default-esm",
    "extensionsToTreatAsEsm": [".ts"]
  }
}

Singleton Pattern

const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined }
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL! })
export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter })
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

Troubleshooting

Error Solution
Cannot find module Check output path matches import, run prisma generate
ERR_REQUIRE_ESM Switch from require() to import
Cannot use import outside module Add "type": "module" to package.json
SSL certificate errors Add ssl: { rejectUnauthorized: false } to adapter
Connection timeouts Configure pool settings explicitly on adapter

Resources

相关技能 Related Skills