brackt/server/db.ts
Chris Parsons 787b817fa7
Add PgBouncer connection pooling support for Vultr managed PostgreSQL (#271)
Disables prepared statements when PGBOUNCER=true (required for PgBouncer
transaction mode). Adds DATABASE_DIRECT_URL so migrations always use a
direct connection, bypassing the pool.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:15:18 -04:00

31 lines
1.2 KiB
TypeScript

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "~/database/schema";
// Cache the client on globalThis so HMR re-evaluations and multiple server
// modules share a single connection pool instead of each opening their own.
declare global {
// eslint-disable-next-line no-var
var __pgClient: ReturnType<typeof postgres> | undefined;
// eslint-disable-next-line no-var
var __pgDb: ReturnType<typeof drizzle<typeof schema>> | undefined;
}
function getDb() {
if (!globalThis.__pgDb) {
if (!process.env.DATABASE_URL) throw new Error("DATABASE_URL is required");
globalThis.__pgClient ??= postgres(process.env.DATABASE_URL, {
prepare: process.env.PGBOUNCER !== "true",
});
globalThis.__pgDb = drizzle(globalThis.__pgClient, { schema });
}
return globalThis.__pgDb;
}
// Export a Proxy so callers can use `db.query.foo` etc. without calling getDb() themselves.
// The proxy defers the DATABASE_URL check until the first actual property access.
export const db = new Proxy({} as ReturnType<typeof drizzle<typeof schema>>, {
get(_target, prop) {
return getDb()[prop as keyof ReturnType<typeof drizzle<typeof schema>>];
},
});