.env.example and the README still told people to use pgCat on :6432, the exact setup that hangs on every parameterised query. With no prod and one backend instance there is nothing for a pooler to multiplex, and postgres-js already pools in-process, so DATABASE_URL now points at Postgres on :5432 in .env.example, dev-env.sh and drizzle.config.ts. prepare:false is kept in src/db/index.ts on purpose, so adding PgBouncer later (tested working) is a config change rather than a code change. The long measurement narrative in that file's comment is cut to the decision and the pointer to PLAN.md, where the numbers now live.
28 lines
1.1 KiB
TypeScript
28 lines
1.1 KiB
TypeScript
import { drizzle } from "drizzle-orm/postgres-js";
|
|
import postgres from "postgres";
|
|
import * as schema from "./schema";
|
|
|
|
// No pooler in front of this for the MVP: DATABASE_URL points straight at
|
|
// Postgres, and postgres-js already pools connections in-process (`max`).
|
|
//
|
|
// `prepare: false` is kept deliberately so a transaction-mode pooler can be
|
|
// added later without touching this file. Which one matters - measured
|
|
// 2026-10-20: through pgCat 1.2.0 any query with a bind parameter hangs
|
|
// forever (every Drizzle query has one), while PgBouncer 1.22 in transaction
|
|
// mode runs the same queries and passes scripts/e2e-authz.sh. See PLAN.md.
|
|
//
|
|
// Migrations go straight at Postgres either way: drizzle.config.ts cannot
|
|
// pass `prepare: false`, and drizzle-kit hung at commit through pgCat.
|
|
const connectionString = process.env.DATABASE_URL;
|
|
if (!connectionString) {
|
|
throw new Error("DATABASE_URL is not set");
|
|
}
|
|
|
|
const client = postgres(connectionString, {
|
|
prepare: false,
|
|
max: Number(process.env.DATABASE_POOL_MAX ?? 10),
|
|
});
|
|
|
|
export const db = drizzle(client, { schema });
|
|
export type Database = typeof db;
|