apps/docs/content/docs.v6/guides/use-prisma-in-pnpm-workspaces.mdx
Prisma is a powerful ORM for managing your database, and when combined with pnpm Workspaces, you can maintain a lean and modular monorepo architecture. In this guide, we’ll walk through setting up Prisma in its own package within a pnpm Workspaces monorepo, enabling maintainable type sharing and efficient database management across your apps.
Before integrating Prisma, you need to set up your project structure. Start by creating a new directory for your project (for example, my-monorepo) and initialize a Node.js project:
mkdir my-monorepo
cd my-monorepo
pnpm init
Next, create a pnpm-workspace.yaml file to define your workspace structure and pin the Prisma version:
touch pnpm-workspace.yaml
Add the following configuration to pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
catalogs:
prisma:
prisma: latest
:::note
The catalogs help you pin a certain version of prisma across your repositories. You can learn more about them here. Explictly pin the lastest version of prisma in the pnpm-workspace.yaml file. At the time of writing, this is version 6.3.1.
:::
Finally, create directories for your applications and shared packages:
mkdir apps
mkdir -p packages/database
This section covers creating a standalone database package that uses Prisma. The package will house all database models and the generated Prisma Client, making it reusable across your monorepo.
Navigate to the packages/database directory and initialize a new package:
cd packages/database
pnpm init
Add Prisma as a development dependency in your package.json using the pinned catalog:
"devDependencies": { // [!code ++]
"prisma": "catalog:prisma" // [!code ++]
} // [!code ++]
Then install Prisma:
pnpm install
Then, add additional dependencies:
pnpm add typescript tsx @types/node @types/pg -D
pnpm add @prisma/adapter-pg pg
:::info
If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of @prisma/adapter-pg. For more information, see Database drivers.
:::
Initalize a tsconfig.json file for your database package:
pnpm tsc --init
Initialize Prisma ORM with an instance of Prisma Postgres in the database package by running the following command:
pnpm prisma init --db
Enter a name for your project and choose a database region.
:::info
We're going to be using Prisma Postgres in this guide. If you're not using a Prisma Postgres database, you won't need to add the --db flag.
:::
This command:
prisma directory containing a schema.prisma file for your database models..env file with your DATABASE_URL (e.g., for Prisma Postgres it should have something similar to DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...").Edit the schema.prisma file to define a User model in your database and specify a custom output directory to generate the Prisma Client. This ensures that generated types are resolved correctly:
generator client {
provider = "prisma-client"
output = "../generated/client" // [!code ++]
}
datasource db {
provider = "postgresql"
}
model User { // [!code ++]
id Int @id @default(autoincrement()) // [!code ++]
email String @unique // [!code ++]
name String? // [!code ++]
} // [!code ++]
Now, create a prisma.config.ts file in the database package to configure Prisma:
import "dotenv/config"; // [!code ++]
import { defineConfig, env } from "prisma/config"; // [!code ++]
export default defineConfig({
// [!code ++]
schema: "prisma/schema.prisma", // [!code ++]
migrations: {
// [!code ++]
path: "prisma/migrations", // [!code ++]
}, // [!code ++]
datasource: {
// [!code ++]
url: env("DATABASE_URL"), // [!code ++]
}, // [!code ++]
}); // [!code ++]
:::note
You'll need to install the dotenv package to load environment variables from the .env file:
pnpm add dotenv
:::
Next, add helper scripts to your package.json to simplify Prisma commands:
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1", // [!code --]
"db:generate": "prisma generate", // [!code ++]
"db:migrate": "prisma migrate dev", // [!code ++]
"db:deploy": "prisma migrate deploy", // [!code ++]
"db:studio": "prisma studio" // [!code ++]
}
}
Use Prisma Migrate to migrate your database changes:
pnpm run db:migrate
When prompted by the CLI, enter a descriptive name for your migration.
Once the migration is successful, create a client.ts file to initialize Prisma Client with a driver adapter:
import { PrismaClient } from "./generated/client"; // [!code ++]
import { PrismaPg } from "@prisma/adapter-pg"; // [!code ++]
const adapter = new PrismaPg({
// [!code ++]
connectionString: process.env.DATABASE_URL, // [!code ++]
}); // [!code ++]
// Use globalThis for broader environment compatibility // [!code ++]
const globalForPrisma = globalThis as typeof globalThis & {
// [!code ++]
prisma?: PrismaClient; // [!code ++]
}; // [!code ++]
// Named export with global memoization // [!code ++]
export const prisma: PrismaClient = // [!code ++]
globalForPrisma.prisma ?? // [!code ++]
new PrismaClient({
// [!code ++]
adapter, // [!code ++]
}); // [!code ++]
if (process.env.NODE_ENV !== "production") {
// [!code ++]
globalForPrisma.prisma = prisma; // [!code ++]
} // [!code ++]
Then, create an index.ts file to re-export the instance of Prisma Client and all generated types:
export { prisma } from "./client"; // [!code ++]
export * from "./generated/client"; // [!code ++]
At this point, your shared database package is fully configured and ready for use across your monorepo.
Now that the database package is set up, create a frontend application (using Next.js) that uses the shared Prisma Client to interact with your database.
Navigate to the apps directory:
cd ../../apps
Create a new Next.js app named web:
pnpm create next-app@latest web --yes
:::note[important]
The --yes flag uses default configurations to bootstrap the Next.js app (which in this guide uses the app router without a src/ directory and pnpm as the installer).
Additionally, the flag may automatically initialize a Git repository in the web folder. If that happens, please remove the .git directory by running rm -r .git.
:::
Then, navigate into the web directory:
cd web/
Copy the .env file from the database package to ensure the same environment variables are available:
cp ../../packages/database/.env .
Open the package.json file of your Next.js app and add the shared database package as a dependency:
"dependencies": {
"database": "workspace:*", // [!code ++]
// additional dependencies
// ...
}
Run the following command to install the database package:
pnpm install
database package in your app codeModify your Next.js application code to use Prisma Client from the database package. Update app/page.tsx as follows:
import { prisma } from "database"; // [!code ++]
export default async function Home() {
// [!code ++]
const user = await prisma.user.findFirst({
// [!code ++]
select: {
// [!code ++]
name: true, // [!code ++]
}, // [!code ++]
}); // [!code ++]
return (
// [!code ++]
<div>
{" "}
// [!code ++]
{user?.name && <p>Hello from {user.name}</p>} // [!code ++]
{!user?.name && <p>No user has been added to the database yet. </p>} // [!code ++]
</div> // [!code ++]
); // [!code ++]
} // [!code ++]
This code demonstrates importing and using the shared Prisma Client to query your User model.
Add the following scripts to the root package.json of your monorepo. They ensure that database migrations, type generation, and app builds run in the proper order:
"scripts": {
"build": "pnpm --filter database db:deploy && pnpm --filter database db:generate && pnpm --filter web build", // [!code ++]
"start": "pnpm --filter web start", // [!code ++]
"dev": "pnpm --filter database db:generate && pnpm --filter web dev", // [!code ++]
"studio": "pnpm --filter database db:studio" // [!code ++]
}
Then head back to the root of the monorepo:
cd ../../
Start your development server by executing:
pnpm run dev
Open your browser at http://localhost:3000 to see your app in action.
There shouldn't be data in your database yet. You can execute pnpm run studio in your CLI to start a Prisma Studio in http://localhost:5555 to interact with your database and add data to it.
You have now created a monorepo that uses Prisma ORM effectively, with a shared database package integrated into a Next.js application.
For further exploration and to enhance your setup, consider reading the How to use Prisma ORM with Turborepo guide.