Prisma ORM 6 -> 7 Upgrade Notes, and Some Thoughts on the Prisma Team's Upgrade Philosophy
2025年12月3日Elecmonkey
This article was translated by AI and has not been manually reviewed.
Upgrade Process
-
Upgrade dependencies:
- Update
prismaand@prisma/clientto ^7.0.1.
- Update
-
Enable ESM support:
- Add
"type": "module"topackage.json. - Update
compilerOptions.targetintsconfig.jsontoES2023to support top-level await and modern module features.
- Add
-
Migrate Prisma configuration:
- Add a
prisma.config.tsfile to centrally manage Prisma CLI configuration, such as the schema path and migration directory. - Modify
prisma/schema.prisma:- Update the provider of
generator clientfromprisma-client-jstoprisma-client. - Specify the output path as
../src/generated/prisma/client, bringing the generated Client code into source control. - Remove the
urlfield from thedatasourceblock. The connection string is now passed directly through code or environment variables.
- Update the provider of
- Add a
-
Fix import paths:
- Update all files referencing Prisma types to point to the new Client generation path.
Moving away from Rust
The most significant change from Prisma 6 to 7 is the migration from Rust to Node.js. After bundling, binary files are no longer included, which very noticeably reduces the size of build artifacts. In addition, in certain special runtime environments, such as edge or non-Node environments, non-JS components always bring all kinds of trouble.
Tencent Cloud EdgeOne has a 125MB package-size limit when deploying projects. Taking one of my own Next.js applications as an example, before the upgrade:
npx edgeone pages build
du -h -d 1
751M ./node_modules
155M ./.next
135M ./.edgeone
292K ./src
The final deployment size reached 135MB. I do not know how large a blank demo project would be, but my project really was not complex: a simple login feature plus several CRUD pages. So what did I do at the time? I used the official HTTP relay provided by Prisma, Prisma Accelerator. With the Proxy, the build artifact could be reduced to 59MB. The nearest optional relay node was Tokyo. My database server was in a certain cloud provider's Shanghai data center. EdgeOne should theoretically choose a nearby node, and end users were also in mainland China. So every connection had to go through:
flowchart LR
U[终端用户<br />(内地)]
--> E[边缘节点<br />(就近)]
--> A[Prisma Accelerator<br />(Tokyo)]
--> DB[数据库<br />(上海)]
--> A2[Prisma Accelerator<br />(Tokyo)]
--> E2[边缘节点<br />(就近)]
--> U2[终端用户<br />(内地)]
The latency was extremely absurd. But I did not want to maintain my own server to self-host the Next.js application, so I could only make do.
After upgrading to Prisma 7, without Prisma Accelerator and with Node.js running pg and @prisma/adapter-pg, I built again:
npx edgeone pages build
du -h -d 1
697M ./node_modules
234M ./.next
61M ./.edgeone
580K ./src
Finally, I got rid of that proxy layer. I did not test how much performance this trade-off traded away, but because it satisfied my needs, I am very satisfied (laughs).
I suspect performance may not necessarily decrease. The data-transfer overhead between binaries and JS is still quite large...
Where the generated files place?
Prisma 6 generates Prisma Client code under node_modules. After upgrading to 7, the code is generated by default into the user's repository rather than node_modules.
The team's stated motivations in the blog can be summarized as follows:
- File watching is inconvenient. Watch and HMR usually do not monitor
node_modules. - Generated code is not colocated with app code, creating a strong "black box" feeling.
- In CI and similar scenarios,
node_modulesis unstable, often cached or ignored, and more likely to cause "it works on my machine" problems.
For me as a developer, the change is that I committed the Prisma Client code to the Git repository. This certainly introduces a risk of inconsistency, but in multi-person collaboration, tools such as precommit scripts and CI bots can ensure that everyone follows the rules. Wherever eslint checks, it checks there too. Of course, speaking of eslint, this Prisma Client should probably still be configured to be ignored by the linter.
By the way, there is another intuitive result: CI/CD deployment no longer needs to repeatedly build Prisma Client code, which has a slight effect on reducing deployment time.
"Reverse Migration", Prisma and Svelte
From what I can see so far, the community response to this upgrade is also fairly positive. As for why Prisma abandoned Rust, the team also explained that using Rust is not conducive to community contributions. This is a widespread issue in the JavaScript community. The fact that the decision-making team considered this point suggests that they care quite a lot about community participation.
This apparent "reverse migration" - where everyone usually migrates from JS to TS, or from Node.js to Rust - reminded me of another example: in Svelte 4, the founder led the team in migrating from TypeScript back to JavaScript. That migration established the fact that today's Svelte codebase uses JSDoc for type checking, but looking back through the discussions on GitHub at the time, opinions were mixed. The author's argument that "in a TS library, when people jump to a function name, they land on type definitions, while in a JS library they can directly see the source code" certainly makes sense. But TypeScript is so popular, and it is not as if people are unaware of these problems. That said, JSDoc still uses TypeScript's capabilities for type checking, so it can be considered a different way of "partially using" TypeScript. Many people did not want to support that decision, but no one can say that such a drastic decision was wrong. Svelte is still growing vigorously.