| 1 | --- |
| 2 | title: Connect from Cloudflare Workers |
| 3 | description: Two ways to reach Prisma Postgres from a Worker — the Connect binding for credentials, or Hyperdrive in front of the direct origin for edge-pooled SQL. |
| 4 | --- |
| 5 | |
| 6 | A Worker can consume a Prisma Postgres database two ways. Both start |
| 7 | from the same resources: |
| 8 | |
| 9 | ```typescript |
| 10 | import * as Cloudflare from "alchemy/Cloudflare"; |
| 11 | import * as Drizzle from "alchemy/Drizzle/Postgres"; |
| 12 | import * as Prisma from "alchemy/Prisma"; |
| 13 | import * as SQL from "alchemy/SQL/Postgres"; |
| 14 | import * as Effect from "effect/Effect"; |
| 15 | import * as HttpServerResponse from "effect/http/HttpServerResponse"; |
| 16 | |
| 17 | const project = yield* Prisma.Project("app", { createDatabase: false }); |
| 18 | const postgres = yield* Prisma.Postgres("db", { project }); |
| 19 | const connection = yield* Prisma.Connection("api", { |
| 20 | database: postgres, |
| 21 | }); |
| 22 | ``` |
| 23 | |
| 24 | ## Over Hyperdrive |
| 25 | |
| 26 | Front the connection's direct `origin` with a Hyperdrive config and |
| 27 | query it with `SQL.Postgres` — Hyperdrive pools and accelerates the |
| 28 | TCP connection at the edge: |
| 29 | |
| 30 | ```typescript |
| 31 | const hyperdrive = yield* Cloudflare.Hyperdrive.Connection("api-hd", { |
| 32 | origin: connection.origin.as<Prisma.PostgresOrigin>(), |
| 33 | }); |
| 34 | |
| 35 | export default Cloudflare.Worker( |
| 36 | "api", |
| 37 | { |
| 38 | main: import.meta.filename, |
| 39 | compatibility: { flags: ["nodejs_compat"] }, |
| 40 | }, |
| 41 | Effect.gen(function* () { |
| 42 | const hd = yield* Cloudflare.Hyperdrive.Connect(hyperdrive); |
| 43 | const sql = yield* SQL.Postgres({ url: hd.connectionString }); |
| 44 | |
| 45 | return { |
| 46 | fetch: Effect.gen(function* () { |
| 47 | const users = yield* sql`SELECT * FROM users`; |
| 48 | return yield* HttpServerResponse.json(users); |
| 49 | }), |
| 50 | }; |
| 51 | }).pipe(Effect.provide(Cloudflare.Hyperdrive.ConnectBinding)), |
| 52 | ); |
| 53 | ``` |
| 54 | |
| 55 | Prefer [Drizzle](/cloudflare/data/drizzle)? Swap the client: |
| 56 | `Drizzle.Postgres(hd.connectionString, { relations })`. |
| 57 | |
| 58 | ## With the Connect binding |
| 59 | |
| 60 | When you don't need edge pooling, bind the connection directly. The |
| 61 | binding carries the connection's outputs into the Worker as secret |
| 62 | text bindings, and the runtime client hands back `Redacted` URLs: |
| 63 | |
| 64 | ```typescript |
| 65 | export default Cloudflare.Worker( |
| 66 | "api", |
| 67 | { |
| 68 | main: import.meta.filename, |
| 69 | compatibility: { flags: ["nodejs_compat"] }, |
| 70 | }, |
| 71 | Effect.gen(function* () { |
| 72 | const db = yield* Prisma.Connect(connection); |
| 73 | const sql = yield* SQL.Postgres({ url: db.databaseUrl }); |
| 74 | |
| 75 | return { |
| 76 | fetch: Effect.gen(function* () { |
| 77 | const users = yield* sql`SELECT * FROM users`; |
| 78 | return yield* HttpServerResponse.json(users); |
| 79 | }), |
| 80 | }; |
| 81 | }).pipe(Effect.provide(Prisma.ConnectBinding)), |
| 82 | ); |
| 83 | ``` |
| 84 | |
| 85 | `db.databaseUrl` prefers the pooled endpoint, so short-lived Worker |
| 86 | connections share Prisma's pooler instead of opening a direct |
| 87 | connection per request. Both examples enable `nodejs_compat` because |
| 88 | the Postgres driver uses Node.js networking and crypto APIs. |
| 89 | |
| 90 | ## Where next |
| 91 | |
| 92 | - [Hyperdrive](/cloudflare/data/hyperdrive) — caching, mTLS, and the |
| 93 | rest of the Hyperdrive surface. |
| 94 | - [Connections](/prisma/data/connections) — every connection output |
| 95 | and the origin shape. |
| 96 | - [SQL clients](/sql) — `SQL.Postgres`, layers, and Drizzle. |