Getting StartedConnect your framework
Drizzle
Drizzle ORM with node-postgres or postgres.js against CapyDB.
Environment
DATABASE_URL="postgres://user:password@host:6432/db?sslmode=require"
DATABASE_DIRECT_URL="postgres://user:password@host:5432/db?sslmode=require"Runtime client
import { drizzle } from 'drizzle-orm/node-postgres'
export const db = drizzle(process.env.DATABASE_URL!)Or with postgres.js:
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
const client = postgres(process.env.DATABASE_URL!, { prepare: false })
export const db = drizzle(client)prepare: false matters on the pooled URL — transaction pooling does not support postgres.js's named prepared statements.
Migrations
Point drizzle-kit at the direct URL:
import { defineConfig } from 'drizzle-kit'
export default defineConfig({
dialect: 'postgresql',
schema: './src/schema.ts',
out: './drizzle',
dbCredentials: {
url: process.env.DATABASE_DIRECT_URL!,
},
})npx drizzle-kit migrate # or push, against the direct URLPitfalls
drizzle-kit push/migrateover the pooled URL can hang or fail on DDL; use the direct URL.- postgres.js without
prepare: falsethrowsprepared statement "..." already existsbehind the pooler. - Long transactions get cut by the plan's idle-in-transaction timeout (60–120s depending on plan); keep migration batches reasonable.