Next.js の開発時に Prisma が「too many connections」で接続できない
Next.js の Fast Refresh でモジュールが再評価されるたびに new PrismaClient() が実行され、開発中だけ接続が増え続けるのが原因。
PrismaClient を globalThis にキャッシュして単一インスタンスを使い回せば解消する。
#prisma#connection#nextjs#hot-reload#dev
公開:
要約
Next.js の開発サーバーは Fast Refresh(hot reload)でファイルを保存するたびにモジュールを再評価します。
このとき PrismaClient を生成するモジュールも作り直され、保存ごとに新しいインスタンスと DB 接続が積み上がります。
結果として開発中だけ接続が増え続け、too many connections(PostgreSQL では sorry, too many clients already)に達します。
解決策は単純で、PrismaClient を globalThis にキャッシュし、開発環境では同じインスタンスを使い回すことです。
よくある原因
- hot reload でモジュールが再評価され、
new PrismaClient()が繰り返し実行される。 - モジュールスコープで直接インスタンスを生成しており、再読み込みのたびに別接続になる。
- 開発サーバーを長時間起動したままにして、DB の最大接続数に到達する。
本番ビルドでは hot reload が無いため再現せず、開発時だけ起きるのが特徴です。
解決策
1. globalThis にインスタンスをキャッシュする
公式の Database connections が推奨する書き方です。
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}グローバル変数は hot reload で初期化されないため、2 回目以降は既存インスタンスを再利用します。
2. アプリ側は常にこのモジュールを読み込む
import { prisma } from "@/lib/prisma";
const users = await prisma.user.findMany();各所で new PrismaClient() せず、必ずこの単一モジュール経由で使います。
3. 滞留した接続を解放する
すでに接続が詰まっている場合は、開発サーバー(next dev)を一度止めて再起動すれば、開いたままの接続が解放されます。