## Introduction

Prisma ORM provides type-safe database access, and [Cloudflare Workers](https://workers.cloudflare.com/) enables you to deploy serverless code at the edge. Together with [Prisma Postgres](https://www.prisma.io/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](https://github.com/prisma/prisma-examples/tree/latest/orm/cloudflare-workers).

## Prerequisites
- [Node.js 20+](https://nodejs.org)
- A [Cloudflare account](https://dash.cloudflare.com/sign-up/workers-and-pages)

## 1. Set up your project

Create a new Cloudflare Workers project:

```terminal
npm create cloudflare@latest prisma-cloudflare-worker -- --type=hello-world --ts=true --git=true --deploy=false
```

Navigate into the newly created project directory:

```terminal
cd prisma-cloudflare-worker
```

## 2. Install and configure Prisma

### 2.1. Install dependencies

To get started with Prisma, you'll need to install a few dependencies:

```terminal
npm install prisma dotenv-cli @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg dotenv 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](/orm/overview/databases/database-drivers).

:::

Once installed, initialize Prisma in your project:

```terminal
npx prisma init --db
```

:::info
You'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 a `schema.prisma` file
- A `prisma.config.ts` file with your Prisma configuration
- A `.env` file with a `DATABASE_URL` already 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`:

```json file=wrangler.jsonc
{
  "name": "prisma-cloudflare-worker",
  "main": "src/index.ts",
  //add-start
  "compatibility_flags": ["nodejs_compat"],
  //add-end
  "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`:

```prisma file=prisma/schema.prisma
generator client {
  provider = "prisma-client"
  // add-next-line
  runtime  = "cloudflare"
  output   = "../src/generated/prisma"
}

datasource db {
  provider = "postgresql"
}

//add-start
model User {
  id    Int    @id @default(autoincrement())
  email String
  name  String
}
//add-end
```

:::note

Both the `cloudflare` and `workerd` runtimes are supported. Read more about runtimes [here](/orm/prisma-schema/overview/generators#field-reference).

:::

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:

```json file=package.json
{
  "scripts": {
    //add-start
    "migrate": "prisma migrate dev",
		"generate": "prisma generate",
		"studio": "prisma studio"
    //add-end
    // ... existing scripts
  }
}
```

### 2.5. Run migrations and generate Prisma Client

Now, run the following command to create the database tables:

```terminal
npm run migrate
```

When prompted, name your migration (e.g., `init`).

Then generate the Prisma Client:

```terminal
npm run generate
```

This 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:

```typescript file=src/index.ts
//add-start
import { PrismaClient } from './generated/prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';

export interface Env {
  DATABASE_URL: string;
}
//add-end

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:

```typescript file=src/index.ts
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> {
    //add-start
    const path = new URL(request.url).pathname;
    if (path === '/favicon.ico')
      return new Response('Resource not found', {
        status: 404,
        headers: {
          'Content-Type': 'text/plain',
        },
      });
    //add-end

    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:

```typescript file=src/index.ts
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',
        },
      });

    //add-start
    const adapter = new PrismaPg({
      connectionString: env.DATABASE_URL,
    });

    const prisma = new PrismaClient({
      adapter,
    });
    //add-end

    return new Response('Hello World!');
  },
} satisfies ExportedHandler<Env>;
```

:::warning

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:

```typescript file=src/index.ts
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,
    });

    //add-start
    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();
    //add-end

    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:

```typescript file=src/index.ts
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:

```terminal
npx wrangler types --no-strict-vars
```

Then start the development server:

```terminal
npm run dev
```

Open [`http://localhost:8787`](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:

```terminal
npm run studio
```

This 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.

```terminal
npx wrangler secret put DATABASE_URL
```

When prompted, paste your database connection string from the `.env` file.

### 4.2. Deploy your Worker

Deploy your Worker to Cloudflare:

```terminal
npm run deploy
```

Once 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](https://hono.dev/) for a more robust routing framework with Cloudflare Workers (see our [Hono guide](/guides/hono))
- Enable query caching with [Prisma Postgres](/postgres/database/caching) for better performance

### More info

- [Prisma Documentation](/orm/overview/introduction)
- [Cloudflare Workers Documentation](https://developers.cloudflare.com/workers/)
- [Deploy to Cloudflare](/orm/prisma-client/deployment/edge/deploy-to-cloudflare)

---

# How to use Prisma ORM and Prisma Postgres with Clerk Auth and Astro