Cloudflare Workers
Learn how to use Prisma ORM in a Cloudflare Workers project
Introduction
Prisma ORM provides type-safe database access, and Cloudflare Workers enables you to deploy serverless code at the edge. Together with Prisma Postgres, you get a globally distributed backend with low-latency database access.
In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in a Cloudflare Workers project. You can find a complete example of this guide on GitHub.
Prerequisites
1. Set up your project
Create a new Cloudflare Workers project:
npm create cloudflare@latest prisma-cloudflare-worker -- --type=hello-world --ts=true --git=true --deploy=falseNavigate into the newly created project directory:
cd prisma-cloudflare-worker2. Install and configure Prisma
2.1. Install dependencies
To get started with Prisma, you'll need to install a few dependencies:
npm install prisma dotenv-cli @types/pg --save-devnpm install @prisma/client @prisma/adapter-pg dotenv pgIf 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.
Once installed, initialize Prisma in your project:
npx prisma init --dbYou'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Cloudflare Workers Project"
This will create:
- A
prisma/directory with aschema.prismafile - A
prisma.config.tsfile with your Prisma configuration - A
.envfile with aDATABASE_URLalready set
2.2. Enable Node.js compatibility in Cloudflare Workers
Cloudflare Workers needs Node.js compatibility enabled to work with Prisma. Add the nodejs_compat compatibility flag to your wrangler.jsonc:
{
"name": "prisma-cloudflare-worker",
"main": "src/index.ts",
"compatibility_flags": ["nodejs_compat"],
"compatibility_date": "2024-01-01"
}2.3. Define your Prisma Schema
In the prisma/schema.prisma file, add the following User model and set the runtime to cloudflare:
generator client {
provider = "prisma-client"
runtime = "cloudflare"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User {
id Int @id @default(autoincrement())
email String
name String
} Both the cloudflare and workerd runtimes are supported. Read more about runtimes here.
This creates a User model with an auto-incrementing ID, email, and name.
2.4. Configure Prisma scripts
Add the following scripts to your package.json to work with Prisma in the Cloudflare Workers environment:
{
"scripts": {
"migrate": "prisma migrate dev",
"generate": "prisma generate",
"studio": "prisma studio"
// ... existing scripts
}
}2.5. Run migrations and generate Prisma Client
Now, run the following command to create the database tables:
npm run migrateWhen prompted, name your migration (e.g., init).
Then generate the Prisma Client:
npm run generateThis generates the Prisma Client in the src/generated/prisma/client directory.
3. Integrate Prisma into Cloudflare Workers
3.1. Import Prisma Client and configure types
At the top of src/index.ts, import the generated Prisma Client and the PostgreSQL adapter, and define the Env interface for type-safe environment variables:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
export interface Env {
DATABASE_URL: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
return new Response("Hello World!");
},
} satisfies ExportedHandler<Env>;3.2. Handle favicon requests
Add a check to filter out favicon requests, which browsers automatically send and can clutter your logs:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
export interface Env {
DATABASE_URL: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const path = new URL(request.url).pathname;
if (path === "/favicon.ico")
return new Response("Resource not found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
});
return new Response("Hello World!");
},
} satisfies ExportedHandler<Env>;3.3. Initialize the Prisma Client
Create a database adapter and initialize Prisma Client with it. This must be done for each request in edge environments:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
export interface Env {
DATABASE_URL: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const path = new URL(request.url).pathname;
if (path === "/favicon.ico")
return new Response("Resource not found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
});
const adapter = new PrismaPg({
connectionString: env.DATABASE_URL,
});
const prisma = new PrismaClient({
adapter,
});
return new Response("Hello World!");
},
} satisfies ExportedHandler<Env>;In edge environments like Cloudflare Workers, you create a new Prisma Client instance per request. This is different from long-running Node.js servers where you typically instantiate a single client and reuse it.
3.4. Create a user and query the database
Now use Prisma Client to create a new user and count the total number of users:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
export interface Env {
DATABASE_URL: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const path = new URL(request.url).pathname;
if (path === "/favicon.ico")
return new Response("Resource not found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
});
const adapter = new PrismaPg({
connectionString: env.DATABASE_URL,
});
const prisma = new PrismaClient({
adapter,
});
const user = await prisma.user.create({
data: {
email: `Prisma-Postgres-User-${Math.ceil(Math.random() * 1000)}@gmail.com`,
name: "Jon Doe",
},
});
const userCount = await prisma.user.count();
return new Response("Hello World!");
},
} satisfies ExportedHandler<Env>;3.5. Return the results
Finally, update the response to display the newly created user and the total user count:
import { PrismaClient } from "./generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
export interface Env {
DATABASE_URL: string;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const path = new URL(request.url).pathname;
if (path === "/favicon.ico")
return new Response("Resource not found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
});
const adapter = new PrismaPg({
connectionString: env.DATABASE_URL,
});
const prisma = new PrismaClient({
adapter,
});
const user = await prisma.user.create({
data: {
email: `Prisma-Postgres-User-${Math.ceil(Math.random() * 1000)}@gmail.com`,
name: "Jon Doe",
},
});
const userCount = await prisma.user.count();
//edit-start
return new Response(`\
Created new user: ${user.name} (${user.email}).
Number of users in the database: ${userCount}.
`);
//edit-end
},
} satisfies ExportedHandler<Env>;3.6. Test your Worker locally
First, generate the TypeScript types for your Worker environment:
npx wrangler types --no-strict-varsThen start the development server:
npm run devOpen http://localhost:8787 in your browser. Each time you refresh the page, a new user will be created. You should see output similar to:
Created new user: Jon Doe (Prisma-Postgres-User-742@gmail.com).
Number of users in the database: 5.3.7. Inspect your data with Prisma Studio
To view your database contents, open Prisma Studio:
npm run studioThis will open a browser window where you can view and edit your User table data.
4. Deploy to Cloudflare Workers
4.1. Set your database URL as a secret
Before deploying, you need to set your DATABASE_URL as a secret in Cloudflare Workers. This keeps your database connection string secure in production.
npx wrangler secret put DATABASE_URLWhen prompted, paste your database connection string from the .env file.
4.2. Deploy your Worker
Deploy your Worker to Cloudflare:
npm run deployOnce deployed, Cloudflare will provide you with a URL where your Worker is live (e.g., https://prisma-postgres-worker.your-subdomain.workers.dev).
Visit the URL in your browser, and you'll see your Worker creating users in production!
Summary
You've successfully created a Cloudflare Workers application with Prisma ORM connected to a Prisma Postgres database. Your Worker is now running at the edge with low-latency database access.
Next steps
Now that you have a working Cloudflare Workers app connected to a Prisma Postgres database, you can:
- Add routes to handle different HTTP methods (GET, POST, PUT, DELETE)
- Extend your Prisma schema with more models and relationships
- Implement authentication and authorization
- Use Hono for a more robust routing framework with Cloudflare Workers (see our Hono guide)
- Enable query caching with Prisma Postgres for better performance