Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

Cloudflare D1

This guide shows you how to use Prisma ORM with Cloudflare D1, a serverless SQL database that runs on Cloudflare's edge network. You'll learn how to set up Prisma ORM with D1, handle migrations, and deploy your application to Cloudflare Workers. You can find a deployment-ready example on GitHub.

Before starting this guide, make sure you have:

  • A Cloudflare account
  • Node.js installed (version 20 or higher)
  • Wrangler CLI installed (version 3.39.0 or higher)
  • Basic familiarity with Cloudflare Workers and D1

Run the following command to create a new Cloudflare Worker project:

title="bun"
bunx create-cloudflare d1-tutorial --type hello-world --ts=true --git=true --deploy=false
pnpm
pnpm create cloudflare d1-tutorial --type=hello-world --ts=true --git=true --deploy=false
yarn
yarn create cloudflare d1-tutorial --type=hello-world --ts=true --git=true --deploy=false
npm
npm create cloudflare@latest d1-tutorial -- --type=hello-world --ts=true --git=true --deploy=false

Then navigate into the newly created directory:

cd d1-tutorial

And initialize Prisma ORM in the project:

title="bun"
bunx --bun prisma@prev init --datasource-provider sqlite
pnpm
pnpm dlx prisma@prev init --datasource-provider sqlite
yarn
yarn dlx prisma@prev init --datasource-provider sqlite
npm
npx prisma@prev init --datasource-provider sqlite

And install the Prisma ORM CLI as a development dependency:

title="bun"
bun add --dev prisma@prev
pnpm
pnpm add --save-dev prisma@prev
yarn
yarn add --dev prisma@prev
npm
npm install --save-dev prisma@prev

In your Prisma schema, set the provider of the datasource to sqlite. If you just bootstrapped the Prisma schema with prisma init, also be sure to add the runtime = "cloudflare" to the generator block and the following User model:

title="prisma/schema.prisma"
generator client {

  provider = "prisma-client"

  output   = "../src/generated/prisma"

  runtime  = "cloudflare"

}

datasource db {

  provider = "sqlite"

}

model User { 

  id    Int     @id @default(autoincrement()) 

  email String  @unique

  name  String?

} 

Next, install the required packages:

bun add @prisma/client@7 @prisma/adapter-d1 dotenv
Bash
pnpm add @prisma/client@7 @prisma/adapter-d1 dotenv
Bash
yarn add @prisma/client@7 @prisma/adapter-d1 dotenv
Bash
npm install @prisma/client@7 @prisma/adapter-d1 dotenv

Also, be sure to use a version of the Wrangler CLI that's above wrangler@^3.39.0, otherwise the --remote flag that's used in the next sections won't be available.

Also, be sure to use a version of the Wrangler CLI that's above wrangler@^3.39.0, otherwise the --remote flag that's used in the next sections won't be available.

Run the following command to create a new D1 database:

bunx wrangler@latest d1 create __YOUR_D1_DATABASE_NAME__
Bash
pnpm dlx wrangler@latest d1 create __YOUR_D1_DATABASE_NAME__
Bash
yarn dlx wrangler@latest d1 create __YOUR_D1_DATABASE_NAME__
Bash
npx wrangler@latest d1 create __YOUR_D1_DATABASE_NAME__

[!NOTE] The __YOUR_D1_DATABASE_NAME__ is a placeholder that should be replaced with the name you want to give your D1 database. For example, you can use prisma-d1-example.

This command will authenticate you with Cloudflare and ask you to select a Cloudflare account. After that, it will create a new D1 database and output the database ID and name:

Bash
✅ Successfully created DB '__YOUR_D1_DATABASE_NAME__' in region __REGION__
Created your new D1 database.

{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "__YOUR_D1_DATABASE_NAME__",
      "database_id": "<unique-ID-for-your-database>"
    }
  ]
}

Copy the terminal output and add the content to your wrangler.jsonc file. This file is used to configure your Cloudflare Worker and its bindings.

To connect your Workers with the D1 instance, add the following binding to your wrangler.jsonc:

wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "d1-tutorial",
  "main": "src/index.ts",
  "compatibility_date": "2025-08-05",
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "__YOUR_D1_DATABASE_NAME__", // to be replaced
      "database_id": "__YOUR_D1_DATABASE_ID__" // to be replaced
    }
  ]
}

[!NOTE] The __YOUR_D1_DATABASE_NAME__ and __YOUR_D1_DATABASE_ID__ in the snippet above are placeholders that should be replaced with the database name and ID of your own D1 instance.

If you weren't able to grab the database ID from the terminal output, you can also find it in the Cloudflare Dashboard or by running npx wrangler d1 list and npx wrangler d1 info __YOUR_D1_DATABASE_NAME__ in your terminal.

This command will authenticate you with Cloudflare and ask you to select a Cloudflare account. After that, it will create a new D1 database and output the database ID and name:

✅ Successfully created DB '__YOUR_D1_DATABASE_NAME__' in region __REGION__

Created your new D1 database.

{

  "d1_databases": [

    {

      "binding": "DB",

      "database_name": "__YOUR_D1_DATABASE_NAME__",

      "database_id": "<unique-ID-for-your-database>"

    }

  ]

}

Copy the terminal output and add the content to your wrangler.jsonc file. This file is used to configure your Cloudflare Worker and its bindings.

To connect your Workers with the D1 instance, add the following binding to your wrangler.jsonc:

title="wrangler.jsonc"
{

  "$schema": "node_modules/wrangler/config-schema.json",

  "name": "d1-tutorial",

  "main": "src/index.ts",

  "compatibility_date": "2025-08-05",

  "d1_databases": [

    {

      "binding": "DB",

      "database_name": "__YOUR_D1_DATABASE_NAME__", // to be replaced

      "database_id": "__YOUR_D1_DATABASE_ID__" // to be replaced

    }

  ]

}

For Cloudflare D1, you'll use Prisma's migration workflow combined with Wrangler CLI to manage your database schema. Since D1 is a serverless SQLite database, we'll use prisma migrate diff to generate migration SQL and then apply it using Wrangler.

Add a .env file in the root of your project with your local database URL:

title=".env"
DATABASE_URL="file:./prisma/db.sqlite"

Also create a prisma.config.ts file in the root of your project:

title="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"),

  },

});

First, create a migrations directory inside the prisma folder and create a file named 0001_init.sql:

mkdir -p prisma/migrations

Now use prisma migrate diff to generate the SQL needed to create your database schema:

bunx prisma migrate diff \

  --from-empty \

  --to-schema prisma/schema.prisma \

  --script > prisma/migrations/0001_init.sql
Bash
pnpm prisma migrate diff \
  --from-empty \
  --to-schema prisma/schema.prisma \
  --script > prisma/migrations/0001_init.sql
Bash
yarn prisma migrate diff \
  --from-empty \
  --to-schema prisma/schema.prisma \
  --script > prisma/migrations/0001_init.sql
Bash
npx prisma migrate diff \
  --from-empty \
  --to-schema prisma/schema.prisma \
  --script > prisma/migrations/0001_init.sql

This command generates a SQL file that contains the statements needed to create your database tables. You can inspect the generated SQL in prisma/migrations/0001_init.sql.

This command generates a SQL file that contains the statements needed to create your database tables. You can inspect the generated SQL in prisma/migrations/0001_init.sql.

Now apply the migration to both your local and remote D1 databases using Wrangler:

# Apply to local database

bunx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --local --file="./prisma/migrations/0001_init.sql"

# Apply to remote database

bunx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --remote --file="./prisma/migrations/0001_init.sql"
Bash
# Apply to local database
pnpm dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --local --file="./prisma/migrations/0001_init.sql"

# Apply to remote database
pnpm dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --remote --file="./prisma/migrations/0001_init.sql"
Bash
# Apply to local database
yarn dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --local --file="./prisma/migrations/0001_init.sql"

# Apply to remote database
yarn dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --remote --file="./prisma/migrations/0001_init.sql"
Bash
# Apply to local database
npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --local --file="./prisma/migrations/0001_init.sql"

# Apply to remote database
npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --remote --file="./prisma/migrations/0001_init.sql"

[!NOTE] Replace __YOUR_D1_DATABASE_NAME__ with the actual name of your D1 database that you created in step 4.

Insert a sample user into each database so the Worker has something to return:

# For the local database

bunx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Local)');" --local

# For the remote database

bunx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Remote)');" --remote
Bash
# For the local database
pnpm dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Local)');" --local

# For the remote database
pnpm dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Remote)');" --remote
Bash
# For the local database
yarn dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Local)');" --local

# For the remote database
yarn dlx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Remote)');" --remote
Bash
# For the local database
npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Local)');" --local

# For the remote database
npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command="INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Remote)');" --remote

[!NOTE] For future schema changes, you can generate new migration files using:

bun

```bash
bunx prisma migrate diff \
  --from-local-d1 \
  --to-schema prisma/schema.prisma \
  --script > migrations/0002_add_new_field.sql
```

pnpm

```bash
pnpm prisma migrate diff \
  --from-local-d1 \
  --to-schema prisma/schema.prisma \
  --script > migrations/0002_add_new_field.sql
```

yarn

```bash
yarn prisma migrate diff \
  --from-local-d1 \
  --to-schema prisma/schema.prisma \
  --script > migrations/0002_add_new_field.sql
```

npm

```bash
npx prisma migrate diff \
  --from-local-d1 \
  --to-schema prisma/schema.prisma \
  --script > migrations/0002_add_new_field.sql
```

Then apply them using the same wrangler d1 execute commands as shown above.

Before adding a Prisma Client query to your Worker, you need to generate Prisma Client with the following command:

bunx prisma generate
Bash
pnpm run dev
Bash
yarn dev
Bash
npm run dev

Now you can open your browser at http://localhost:8787 to see the result of the database query:

no-copy
[{ id: 1, email: "jane@prisma.io", name: "Jane Doe (Local)" }];

In order to query your database from the Worker using Prisma ORM, you need to:

  1. Add the DB binding to the Env interface. This DB name matches the binding name you configured in wrangler.jsonc. (Alternatively, you can run npx wrangler types to generate the Env type from the binding in a separate file called worker-configuration.d.ts.)
  2. Instantiate PrismaClient using the PrismaD1 driver adapter, passing env.DB which accesses your D1 database binding.
  3. Send a query using Prisma Client and return the result.

Open src/index.ts and replace the entire content with the following:

title="src/index.ts"
import { PrismaClient } from "./generated/prisma/client";

import { PrismaD1 } from "@prisma/adapter-d1";

export interface Env {

  DB: D1Database;

}

export default {

  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {

    const adapter = new PrismaD1(env.DB);

    const prisma = new PrismaClient({ adapter });

    const users = await prisma.user.findMany();

    const result = JSON.stringify(users);

    ctx.waitUntil(prisma.$disconnect()); // or just await prisma.$disconnect()

    return new Response(result);

  },

};

We explicitly call prisma.$disconnect() here to guarantee timely release of resources or else the worker might run out of memory.

With the database query in place and Prisma Client generated, you can run the Worker locally.

If your Worker needs any environment variables, create a .dev.vars file in the root of your project. For this example, we don't need any additional environment variables since the D1 binding is already configured in wrangler.jsonc.

Now run the Worker locally:

bun run dev
Bash
pnpm run deploy
Bash
yarn deploy
Bash
npm run deploy

Your deployed Worker is accessible via https://d1-tutorial.USERNAME.workers.dev (replace USERNAME with your Cloudflare account username). If you navigate your browser to that URL, you should see the following data that's queried from your remote D1 database:

no-copy
[{ id: 1, email: "jane@prisma.io", name: "Jane Doe (Remote)" }];

Now you can open your browser at http://localhost:8787 to see the result of the database query:

[{ id: 1, email: "jane@prisma.io", name: "Jane Doe (Local)" }];

To deploy the Worker, run the following command:

bun run deploy

Your deployed Worker is accessible via https://d1-tutorial.USERNAME.workers.dev (replace USERNAME with your Cloudflare account username). If you navigate your browser to that URL, you should see the following data that's queried from your remote D1 database:

[{ id: 1, email: "jane@prisma.io", name: "Jane Doe (Remote)" }];

Now that you've set up Prisma ORM with Cloudflare D1, you can:

  • Add more complex queries, such as filters, relations, and aggregations
  • Set up Prisma Studio for database management
  • Implement database monitoring
  • Add automated tests

For more information:

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu