Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/realtime/src/database/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ import { env } from '@/env'
const logger = createLogger('SocketDatabase')

const connectionString = env.DATABASE_URL
/**
* Server-side safety net for runaway queries and abandoned transactions.
* See `packages/db/index.ts` for rationale.
*/
const socketDb = drizzle(
postgres(connectionString, {
prepare: false,
idle_timeout: 10,
connect_timeout: 20,
max: 30,
onnotice: () => {},
connection: {
options: '-c statement_timeout=90000 -c idle_in_transaction_session_timeout=90000',
},
}),
{ schema }
)
Expand Down
15 changes: 15 additions & 0 deletions packages/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@ if (!connectionString) {
throw new Error('Missing DATABASE_URL environment variable')
}

/**
* Server-side safety net for runaway queries and abandoned transactions:
* - `statement_timeout=90000` kills any single statement still running
* after 90s. Protects against pathological queries.
* - `idle_in_transaction_session_timeout=90000` kills a session that has
* opened a transaction and gone idle for 90s. Protects against
* transactions that hold row locks while waiting on external I/O.
*
* These are last-resort caps — application code should never approach
* them. Migrations or admin scripts that legitimately need longer limits
* must construct their own client with overrides.
*/
const postgresClient = postgres(connectionString, {
prepare: false,
idle_timeout: 20,
connect_timeout: 30,
max: 30,
onnotice: () => {},
connection: {
options: '-c statement_timeout=90000 -c idle_in_transaction_session_timeout=90000',
},
})

export const db = drizzle(postgresClient, { schema })
Loading