Skip to content

Dev server exhausts Postgres connections after ~10 hot reloads #5

@RisingOrange

Description

@RisingOrange

Symptom

After ~10 Turbopack hot-reloads in npm run dev, all DB-touching pages fail with:

Error: Failed query: select ...
[cause]: PostgresError: sorry, too many clients already
  severity: 'FATAL', code: '53300'

Recovery requires restarting the dev server.

Root cause

src/db/index.ts:6 instantiates the Postgres client at module top level with no globalThis caching:

const client = postgres(connectionString);
export const db = drizzle(client, { schema });

Turbopack's HMR re-evaluates this module on every change. Each evaluation opens a new pool (postgres-js default max: 10) and never closes the old one. Postgres's default max_connections is 100, so we hit the cap after ~10 reloads.

Production isn't affected — Next.js doesn't HMR there, the module loads once, the pool lives for the process lifetime.

Proposed fix

Standard pattern: cache the client on globalThis in non-prod so HMR reuses it. Same shape Prisma, Drizzle, and Next.js examples all use.

// src/db/index.ts
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";

const connectionString = process.env.DATABASE_URL!;

const globalForPostgres = globalThis as unknown as {
  __pgClient?: ReturnType<typeof postgres>;
};

const client = globalForPostgres.__pgClient ?? postgres(connectionString);
if (process.env.NODE_ENV !== "production") {
  globalForPostgres.__pgClient = client;
}

export const db = drizzle(client, { schema });

Optional: also cap postgres(..., { max: 10 }) explicitly so any future regression has a smaller blast radius.

Acceptance criteria

  • After 30+ hot-reloads in npm run dev, queries still succeed (no 53300).
  • Production behavior unchanged (single pool per process).
  • No globalThis pollution in production builds (gated on NODE_ENV).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions