空雲 Blog

Eye catchCloudflare で Prisma + PostgreSQL を使う場合、リクエストを超えてインスタンスを使いまわしてはいけない

publication: 2024/10/10
update:2024/10/11

Cloudflare Workers の制限

Cloudflare Workers では、Workers 内で生成したコネクションはリクエストを超えて使いまわすことができません。そのため、Prisma や PostgreSQL などの外部コネクションを使う場合は、リクエストごとに新しいインスタンスを生成する必要があります。D1 のようなコネクションを伴わない DB であれば、インスタンスを使いまわしても問題ありません。

Prisma + PostgreSQL の例

最小限のコードで Prisma インスタンスを使いまわしたらどうなるのかという検証を行いました。以下のリンク先で実際に動作させていますが、一回目は成功するものの、二回目はエラーになります。そして Worker が落ちるので、三回目は成功します。そして失敗と成功を繰り返します。

https://cloudflare-workers-prisma-connection.mofon001.workers.dev/

1export * from "@prisma/adapter-pg";
2import { Pool } from "pg";
3import { PrismaPg } from "@prisma/adapter-pg";
4import { PrismaClient } from "@prisma/client";
5
6export interface Env {
7 DATABASE_URL: string;
8 prisma: Fetcher;
9}
10
11// Errors occur when Prisma instances are used around.
12let prisma: PrismaClient;
13
14export default {
15 async fetch(
16 request: Request,
17 env: Env,
18 _ctx: ExecutionContext
19 ): Promise<Response> {
20 const url = new URL(request.url);
21 if (url.pathname !== "/") return new Response("Not Found", { status: 404 });
22 if (!prisma) {
23 const databaseUrl = new URL(env.DATABASE_URL);
24 const schema = databaseUrl.searchParams.get("schema") ?? undefined;
25 const pool = new Pool({
26 connectionString: env.DATABASE_URL,
27 });
28 const adapter = new PrismaPg(pool, { schema });
29 prisma = new PrismaClient({ adapter });
30 }
31 await prisma.test.create({ data: {} });
32 const result = await prisma.test
33 .findMany()
34 .then((r) => r.map(({ id }) => id));
35 return new Response(JSON.stringify(result, undefined, " "), {
36 headers: { "content-type": "application/json" },
37 });
38 },
39};

  • 出力されたエラー

{"width":"1173px","height":"524px"}

まとめ

Cloudflare Workers で Prisma や PostgreSQL を使う場合は、リクエストごとに新しいインスタンスを生成しましょう。

ちなみに compatibility_flagsnodejs_compat_v2 を有効にし、さらに pg-compat パッケージをインストールすれば、Cloudflare 上で Node.js 環境と同じように pg を直接使うことが出来ます。