# Where Prisma ORM Generates Client Code (and Why) URL: https://www.prisma.io/blog/why-prisma-orm-generates-code-into-node-modules-and-why-it-ll-change Published: 2025-05-23 Updated: 2026-07-06 Authors: Nikolas Burk, Will Madden Tags: orm, education Description: Prisma ORM v7 generates Prisma Client into your project source via the prisma-client generator and a required output path. Learn why earlier versions used node_modules, what changed, and how to migrate. Since Prisma ORM v7, Prisma Client is generated into a folder you choose inside your project source, such as `src/generated/prisma`. The `output` option is required, and the generated code is treated like regular application code. Earlier versions generated the client into `node_modules` by default. This post explains how the current setup works, why the original default existed, and how to migrate if you are still on the old generator. ## Where Prisma Client lives today [#where-prisma-client-lives-today] In Prisma ORM v7, the default generator is [`prisma-client`](https://www.prisma.io/docs/orm/v7/prisma-schema/overview/generators). It requires an explicit `output` path and writes the generated client into your project source tree: ```prisma // prisma/schema.prisma generator client { provider = "prisma-client" // rust-free and ESM output = "../src/generated/prisma" // required } datasource db { provider = "postgresql" } ``` Project configuration, including your database connection, lives in `prisma.config.ts`: ```typescript // 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"), }, }); ``` The fastest way to get a `DATABASE_URL` is [Prisma Postgres](https://www.prisma.io/postgres), the managed PostgreSQL database that integrates natively with Prisma ORM. A single command provisions a database and gives you the connection string to put in your `.env` file: ```shell npm create db ``` After running `prisma generate`, you import the client from the `output` location instead of `@prisma/client`. The rust-free client talks to your database through a driver adapter, so install the one for your database (`npm install @prisma/adapter-pg` for PostgreSQL) and pass it to the constructor: ```typescript import { PrismaClient } from "./generated/prisma/client"; import { PrismaPg } from "@prisma/adapter-pg"; const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); const prisma = new PrismaClient({ adapter }); ``` That's the whole model: the generated client is part of your application code, your build tools see it like any other source file, and nothing in `node_modules` is modified after installation. ## Why Prisma ORM generates code at all [#why-prisma-orm-generates-code-at-all] Since its initial release, Prisma ORM has used *code generation* to produce a database client (called "Prisma Client") that's tailored to your database schema. Prisma Client is auto-generated from the Prisma schema so that it knows the structure of your models and can provide custom, type-safe queries for them. Code generation isn't the most conventional method in the TypeScript ecosystem, and Prisma ORM was one of the first popular libraries to rely on it. The payoff is a client API that matches your schema exactly, with autocomplete and compile-time guarantees for every query. ## Why the client used to live in `node_modules` [#why-the-client-used-to-live-in-node_modules] To keep things familiar for developers, earlier versions of Prisma ORM generated Prisma Client into the `node_modules` folder by default, because that's how developers typically integrate third-party libraries into their applications. A custom location was always possible via the `output` field, but the default gave Prisma ORM unified behavior across frameworks and usage contexts. Generating Prisma Client into `node_modules` led to a magical "it just works™️" developer experience for most people … except when it didn't. Many tools across the JS/TS ecosystem assume that the `node_modules` directory is only modified by your package manager (`npm`, `pnpm`, `yarn` etc.). With Prisma ORM, however, you need to re-generate Prisma Client after every database schema change so the generated code reflects the latest state of your database. That requirement, combined with the `node_modules` default, violated the assumption of many tools in the ecosystem. Because of this, we (and others in the community) had to put *workarounds* in place to keep the DX smooth: * The TS language server doesn't watch for changes in `node_modules`, so the Prisma VS Code extension rebooted the TS language server any time you ran `prisma generate`. * The [`@prisma/nextjs-monorepo-workaround-plugin`](https://www.npmjs.com/package/@prisma/nextjs-monorepo-workaround-plugin) package existed solely to ensure files were copied properly from `node_modules` when Prisma ORM was used in monorepos with Next.js. * Dockerfiles needed dedicated `COPY` steps for `node_modules/.prisma` and `node_modules/@prisma` so the generated client survived multi-stage builds. Workarounds existed in various shapes and forms, from dedicated packages to hardcoded code paths. They all traced back to the same core issue: generated code living in a folder that tools expect to be immutable. ## What changed in Prisma ORM v7 [#what-changed-in-prisma-orm-v7] As part of [making the DX of Prisma ORM simpler and more predictable](https://www.prisma.io/blog/prisma-orm-manifesto) by removing magical behavior and unnecessary abstraction layers, [Prisma ORM v7](https://www.prisma.io/blog/announcing-prisma-orm-7-0-0) made the `prisma-client` generator the default and made the `output` path required. The old `prisma-client-js` generator, with its `node_modules` generation, is in maintenance mode. This approach has several benefits: * **The generated code is treated like regular application code.** You have full control over it and decide how it becomes part of your application bundle. * **More predictability.** File watchers, linters, and bundlers react to `prisma generate` like they would to any other source change, so the old workarounds are no longer needed. * **Compliance with ecosystem assumptions.** Your package manager is the only thing that touches `node_modules`. The new generator also ships without the Rust query engine, supports ESM, and is compatible with various JS runtimes (Node.js, Deno, Bun, Cloudflare Workers, and more). The rust-free client produces up to 90% smaller bundles and executes queries up to 3x faster; [the benchmarks](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) tell the full story. ## Migrating from `prisma-client-js` [#migrating-from-prisma-client-js] If your project still uses the `prisma-client-js` generator, the switch is small: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "../src/generated/prisma" } ``` Then: 1. Run `npx prisma generate`. 2. Update your imports from `@prisma/client` to your `output` location, e.g. `./generated/prisma/client`. 3. Install the driver adapter for your database (`npm install @prisma/adapter-pg` for PostgreSQL) and construct the client with it: `new PrismaClient({ adapter })`, as shown above. 4. Exclude the generated folder from linting and formatting (for example in your ESLint ignore config). The code is generated, so lint findings there don't matter, and tools like the Next.js dev server can otherwise halt on them. ## Common errors and how to fix them [#common-errors-and-how-to-fix-them] **"An output path is required for the `prisma-client` generator"**: add an `output` field to your generator block, as shown above. Any location in your source tree works; we suggest `../src/generated/prisma` (relative to your schema file). **"`PrismaClient` needs to be constructed with a non-empty, valid `PrismaClientOptions`"**: the `prisma-client` generator connects through a driver adapter. Install the adapter for your database (for PostgreSQL, `@prisma/adapter-pg`) and pass it to the constructor: `new PrismaClient({ adapter })`. **"@prisma/client did not initialize yet. Please run `prisma generate`"**: this error comes from importing `@prisma/client` before the client was generated. Run `npx prisma generate` (it also runs automatically on `npm install` via the `postinstall` hook in many setups). If you're on the `prisma-client` generator, check that you're importing from your `output` path instead of `@prisma/client`. **Lint or type errors inside the generated folder**: exclude the `output` directory from ESLint, Prettier, and any strict `tsconfig` includes. Generated code is meant to be consumed, and it doesn't need to pass your project's style rules. **Docker builds and monorepos**: with the client generated into your source tree, it's bundled with your application like any other module. The `COPY node_modules/.prisma` steps and the `@prisma/nextjs-monorepo-workaround-plugin` are no longer needed on the `prisma-client` generator. ## Looking ahead: Prisma 8 [#looking-ahead-prisma-8] [Prisma 8](https://www.prisma.io/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app) is the next generation of Prisma ORM and the version npm installs by default. Prisma ORM v7, which this post covers, remains supported, with its docs at [prisma.io/docs/orm/v7](https://www.prisma.io/docs/orm/v7). In Prisma 8, you describe your models and relationships in a single data contract, Prisma generates the migrations, and you or your coding agent write type-safe queries in terms of your models. Every query returns structured, machine-readable output, and every operation comes with guardrails, so humans and AI agents can iterate quickly without breaking things. It's also fast. In [our published benchmark](https://www.prisma.io/blog/prisma-next-performance-benchmark), a fork of the open-source drizzle-benchmarks suite, Prisma 8 reaches roughly 90% of the raw `pg` driver's speed, holds p95 latency around 4 ms at 6,000 to 7,000 requests/second, and keeps scaling to about 12,500 requests/second, roughly 50% beyond where Prisma 7 tops out. The client ships at about 148.5 KB gzipped, around 9x smaller than Prisma 7's, which translates directly into faster cold starts on serverless and edge. Prisma 8 pairs with [Prisma Postgres](https://www.prisma.io/postgres) the same way v7 does: provision a database in one step and connect with a single URL. If you're starting a new project, especially one built with AI coding agents, use Prisma 8. ## Wrap-up [#wrap-up] Prisma Client now lives where the rest of your code lives. That single decision removed a whole category of workarounds and made Prisma ORM more predictable across bundlers, monorepos, and deploy targets. If you're starting fresh, `npm create db` gives you a Prisma Postgres database and a ready-to-run v7 setup in one step. As always, [reach out to us on X](https://pris.ly/x) or [join our Discord](https://pris.ly/discord) if you have any feedback or questions!