1---
2title: Prisma ORM with Postgres
3description: Deploy Prisma ORM v8 on Cloudflare Workers with Neon Postgres, Hyperdrive, controlled migrations, and Effect-native queries.
4---
5
6[Contracts](/sql/prisma/contracts) · [Query API](/sql/prisma/postgres) · [Runnable example](https://github.com/alchemy-run/alchemy/tree/main/examples/cloudflare-neon-prisma)
7
8:::caution
9Requires Prisma ORM **8.0.0-rc** and **PostgreSQL 17+**. Pin the ORM and CLI versions used by your Alchemy release.
10:::
11
12## Install the dependencies
13
14```sh
15bun add alchemy effect @prisma/orm-postgres arktype
16bun add -d prisma
17```
18
19[Cloudflare setup](/cloudflare/setup) · [Neon setup](/neon/setup) · [Define a contract](/sql/prisma/contracts)
20
21## Configure validation for Workers
22
23```typescript
24// src/prisma/validation.ts
25import { configure } from "arktype/config";
26
27configure({ jitless: true });
28```
29
30Import the bootstrap before the contract builder:
31
32```typescript
33import "./validation.ts";
34import { defineContract } from "alchemy/Prisma/ORM";
35```
36
37If your package uses `"sideEffects": false`, preserve this module:
38
39```json
40{ "sideEffects": ["./src/prisma/validation.ts"] }
41```
42
43PSL-first projects skip this step.
44
45## Provision the database and migrations
46
47```typescript
48// src/db.ts
49import * as Neon from "alchemy/Neon";
50import * as Prisma from "alchemy/Prisma";
51import * as Effect from "effect/Effect";
52
53export const Db = Effect.gen(function* () {
54 const contract = yield* Prisma.Contract("contract");
55 const project = yield* Neon.Project("app-db");
56 const branch = yield* Neon.Branch("app-branch", { project });
57
58 yield* Prisma.Migrate("migrate", {
59 url: branch.connectionUri,
60 contract,
61 });
62
63 return branch;
64});
65```
66
67[Migration workflow](/sql/prisma/migrations)
68
69## Add Hyperdrive
70
71```typescript
72// src/db.ts
73import * as Cloudflare from "alchemy/Cloudflare";
74
75export const Hyperdrive = Effect.gen(function* () {
76 const branch = yield* Db;
77 return yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", {
78 origin: branch.origin,
79 caching: { disabled: true },
80 });
81});
82```
83
84Caching is disabled so reads immediately reflect writes. [Hyperdrive guide](/cloudflare/data/hyperdrive).
85
86## Connect in a Worker
87
88```typescript
89// src/api.ts
90import * as Cloudflare from "alchemy/Cloudflare";
91import * as PrismaPostgres from "alchemy/Prisma/ORM/Postgres";
92import * as Effect from "effect/Effect";
93import * as HttpServerResponse from "effect/http/HttpServerResponse";
94import { contract } from "./prisma/contract.ts";
95import { Hyperdrive } from "./db.ts";
96
97export default class Api extends Cloudflare.Worker<Api>()(
98 "Api",
99 { main: import.meta.url },
100 Effect.gen(function* () {
101 const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);
102 const db = yield* PrismaPostgres.Postgres(conn.connectionString, { contract });
103
104 return {
105 fetch: Effect.gen(function* () {
106 const users = yield* db.orm.public.User.all();
107 return yield* HttpServerResponse.json({ users });
108 }),
109 };
110 }).pipe(Effect.provide(Cloudflare.Hyperdrive.ConnectBinding)),
111) {}
112```
113
114[Connection lifecycle](/sql/effect-sql/lifecycle)
115
116## Use a PSL contract
117
118```typescript
119import { makeDatabase } from "./prisma/generated/client.ts";
120
121const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);
122const db = yield* makeDatabase(conn.connectionString);
123```
124
125[Generate the PSL client](/sql/prisma/contracts#query-a-psl-contract) before compiling. The handler and binding layer stay the same.
126
127## Wire the stack
128
129```typescript
130// alchemy.run.ts
131import * as Alchemy from "alchemy";
132import * as Cloudflare from "alchemy/Cloudflare";
133import * as Neon from "alchemy/Neon";
134import * as Prisma from "alchemy/Prisma";
135import * as Effect from "effect/Effect";
136import * as Layer from "effect/Layer";
137import Api from "./src/api.ts";
138
139export default Alchemy.Stack(
140 "PrismaWorker",
141 {
142 providers: Layer.mergeAll(
143 Cloudflare.providers(),
144 Neon.providers(),
145 Prisma.providers(),
146 ),
147 state: Alchemy.localState(),
148 },
149 Effect.gen(function* () {
150 const api = yield* Api;
151 return { url: api.url };
152 }),
153);
154```
155
156## Deploy and query
157
158```sh
159bun alchemy deploy
160curl https://<your-worker>.workers.dev
161```
162
163This demo route is public. Add authentication before exposing private data.
164
165## Clean up
166
167```sh
168bun alchemy destroy
169```
170
171Destroy removes the example's Worker, Hyperdrive configuration, and Neon resources, including the database data.
172
173## Runnable examples
174
175- [TypeScript-first example](https://github.com/alchemy-run/alchemy/tree/main/examples/cloudflare-neon-prisma).
176- [PSL-first example](https://github.com/alchemy-run/alchemy/tree/main/examples/cloudflare-neon-prisma-psl).
177- [Prisma queries and transactions](/sql/prisma/postgres).
178- [Choose another SQL provider](/sql/databases).