Raypx

Database

PostgreSQL database with Drizzle ORM for type-safe queries.

Raypx uses PostgreSQL as its database, managed through Drizzle ORM for type-safe queries. The database layer lives in the @raypx/database workspace package.

Package Structure

Connection Management

The database connection is created with createDb() from packages/database/src/client.ts:

packages/database/src/client.ts
export function createDb(options: Partial<DatabaseConfig> = {}): DbClient {
  if (cachedClient) return cachedClient.db

  const env = envs()
  const databaseUrl = options.databaseUrl ?? env.DATABASE_URL

  const postgresOptions = {
    max: options.postgresOptions?.max ?? env.DATABASE_POOL_MAX ?? 10,
    idle_timeout: options.postgresOptions?.idle_timeout ?? env.DATABASE_IDLE_TIMEOUT ?? 20,
    connect_timeout: 10,
  }

  cachedClient = createClientWithConnection({ databaseUrl, postgresOptions })
  return cachedClient.db
}

Key behaviors:

  • Singleton pattern -- The connection is created once and reused across all requests in the same process.
  • Connection pooling -- Uses postgres.js with configurable pool size (default: 10 connections).
  • Lazy initialization -- The connection is only established on first call to createDb().

Connection Pool Configuration

VariableDefaultDescription
DATABASE_URLRequiredPostgreSQL connection string.
DATABASE_POOL_MAX10Maximum connections in the pool.
DATABASE_IDLE_TIMEOUT20Seconds before an idle connection is closed.

For single-instance deployments, 10-20 connections is recommended. For multi-instance deployments (5+ pods), consider using PgBouncer for external connection pooling.

Environment Variables

.env
DATABASE_URL=postgres://user:password@localhost:5432/raypx
# DATABASE_POOL_MAX=10
# DATABASE_IDLE_TIMEOUT=20

Health Check

A health check endpoint is available to verify database connectivity:

src/lib/db.server.ts
export async function checkDbHealth() {
  const result = await checkDatabaseHealth(getDb())
  return {
    status: result.healthy ? "ok" : "error",
    latency: result.latency,
    ...(result.error ? { error: result.error } : {}),
  }
}

The health check executes SELECT 1 against the database and reports latency in milliseconds.

Exports

The @raypx/database package exports everything you need:

import { createDb, closeDb, checkDatabaseHealth, schema, sql, eq, and, desc } from "@raypx/database"

Next Steps

On this page