Bun workspaces
This guide shows you how to use Prisma ORM in a Bun Workspaces monorepo. You'll set up a shared database package with Prisma ORM, then integrate it into a Next.js app in the same workspace.
- Bun installed
- A Prisma Postgres database (or another supported database)
Before integrating Prisma ORM, 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
bun initmkdir my-monorepo
cd my-monorepo
pnpm initmkdir my-monorepo
cd my-monorepo
yarn initmkdir my-monorepo
cd my-monorepo
npm initNext, add the workspaces array to your root package.json to define your workspace structure:
{
"name": "my-monorepo",
"workspaces": ["apps/*", "packages/*"]
}Finally, create directories for your applications and shared packages:
mkdir apps
mkdir -p packages/databaseThis section covers creating a standalone database package that uses Prisma ORM. The package will house all database models and the generated Prisma ORM client, making it reusable across your monorepo.
Navigate to the packages/database directory and initialize a new package:
cd packages/database
bun initcd packages/database
pnpm initcd packages/database
yarn initcd packages/database
npm initInstall the required Prisma ORM packages and other dependencies:
bun add prisma@prev typescript tsx @types/node @types/pg --dev
bun add @prisma/client@7 @prisma/adapter-pg pgpnpm add prisma@prev typescript tsx @types/node @types/pg --save-dev
pnpm add @prisma/client@7 @prisma/adapter-pg pgyarn add prisma@prev typescript tsx @types/node @types/pg --dev
yarn add @prisma/client@7 @prisma/adapter-pg pgnpm install prisma@prev typescript tsx @types/node @types/pg --save-dev
npm install @prisma/client@7 @prisma/adapter-pg pg[!NOTE] 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.
Initialize Prisma ORM with an instance of Prisma Postgres in the database package by running the following command:
bunx --bun prisma initpnpm prisma inityarn prisma initnpx prisma init[!NOTE]
prisma initcreates the Prisma scaffolding and a localDATABASE_URL. In the next step, create a Prisma Postgres database and replace that value with a directpostgres://...connection string.
This command:
- Creates a
prismadirectory containing aschema.prismafile for your database models. - Creates a
prisma.config.tsfile for configuring Prisma. - Creates a
.envfile with a localDATABASE_URL.
Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:
This command:
- Creates a
prismadirectory containing aschema.prismafile for your database models. - Creates a
prisma.config.tsfile for configuring Prisma. - Creates a
.envfile with a localDATABASE_URL.
Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:
bunx create-dbpnpm dlx create-dbyarn dlx create-dbnpx create-dbEdit the schema.prisma file to add a User model. The default generator already sets output = "../generated/prisma":
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
} If the generated prisma.config.ts comments mention installing dotenv, install it so environment variables load:
bun add dotenvpnpm add dotenvyarn add dotenvnpm install dotenvAdd a scripts section to your database package.json (Bun init may not add one by default):
{
"scripts": {
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev",
"db:deploy": "prisma migrate deploy",
"db:seed": "prisma db seed",
"db:studio": "prisma studio"
}
}Use Prisma Migrate to migrate your database changes:
bun run db:migratepnpm run db:migrateyarn db:migratenpm run db:migrateWhen prompted by the CLI, enter a descriptive name for your migration. After the migration completes, run generate so the Prisma ORM client is created:
When prompted by the CLI, enter a descriptive name for your migration. After the migration completes, run generate so the Prisma ORM client is created:
bun run db:generatepnpm run db:generateyarn db:generatenpm run db:generateCreate a client.ts file to initialize the Prisma ORM client with a driver adapter:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
});
// Use globalThis for broader environment compatibility
const globalForPrisma = globalThis as typeof globalThis & {
prisma?: PrismaClient;
};
export const prisma: PrismaClient =
globalForPrisma.prisma ??
new PrismaClient({
adapter,
});
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}Then, create an index.ts file to re-export the instance of the Prisma ORM client and all generated types:
export { prisma } from "./client";
export * from "./generated/prisma/client";Add a seed script to populate the database with sample users. Create prisma/seed.ts in the database package:
import "dotenv/config";
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 });
async function main() {
await prisma.user.createMany({
data: [
{ email: "alice@example.com", name: "Alice" },
{ email: "bob@example.com", name: "Bob" },
{ email: "charlie@example.com", name: "Charlie" },
],
skipDuplicates: true,
});
console.log("Seed complete.");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});Add the seed option to the existing migrations config in your database package's prisma.config.ts (add the seed line inside migrations):
migrations: {
path: "prisma/migrations",
seed: "bun prisma/seed.ts",
},At this point, your shared database package is fully configured and ready for use across your monorepo.
Add the following scripts to the root package.json of your monorepo. They let you run database and app commands from the root:
"scripts": {
"build": "bun run --filter database db:deploy && bun run --filter database db:generate && bun run --filter web build",
"start": "bun run --filter web start",
"dev": "bun run --filter database db:generate && bun run --filter web dev",
"seed": "bun run --filter database db:seed",
"studio": "bun run --filter database db:studio"
} From the monorepo root, run bun run seed to add sample users. Run bun run studio to open Prisma Studio at http://localhost:5555 to view and edit your data.
Now that the database package is set up, create a frontend application (using Next.js) that uses the shared Prisma ORM client to interact with your database.
Navigate to the apps directory:
cd ../../appsCreate a new Next.js app named web:
bun create next-app@latest web --yesThen, 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:*"
}Run the following command to install the database package:
bun installpnpm installyarn installnpm installModify your Next.js application code to use the Prisma ORM client from the database package. Update app/page.tsx as follows:
import { prisma } from "database";
export default async function Home() {
const user = await prisma.user.findFirst({
select: {
name: true,
},
});
return (
<div>
{user?.name && <p>Hello from {user.name}</p>}
{!user?.name && <p>No user has been added to the database yet.</p>}
</div>
);
}This code demonstrates importing and using the shared Prisma ORM client to query your User model.
Then head back to the root of the monorepo:
cd ../../Start your development server by executing:
bun run devpnpm run devyarn devnpm run devOpen your browser at http://localhost:3000 to see your app in action. You can run bun run studio to open Prisma Studio at http://localhost:5555 to view and edit your data.
Open your browser at http://localhost:3000 to see your app in action. You can run bun run studio to open Prisma Studio at http://localhost:5555 to view and edit your data.
You have now created a monorepo that uses Prisma ORM, with a shared database package integrated into a Next.js application.
To add task orchestration and caching on top of this setup, see the How to use Prisma ORM with Turborepo guide.