bigint GENERATED ALWAYS AS IDENTITY for sequential IDs following PostgreSQL best practices.Database connection
The app uses a shared PostgreSQL connection pool configured inlib/db/index.ts:
lib/db/index.ts
Connection pool best practices
Single shared pool
Single shared pool
Connection limits
Connection limits
Maximum of 10 connections prevents memory exhaustion and respects PostgreSQL limits.
Idle timeout
Idle timeout
Connections idle for 30+ seconds are reclaimed to free up resources.
Fast failure
Fast failure
5-second connection timeout ensures the app doesn’t hang waiting for unavailable connections.
Better Auth tables
Better Auth automatically creates and manages these tables:User table
Custom user fields
type (required)
type (required)
Determines user role:
'employee' for job seekers or 'organization' for companies.profession (required)
profession (required)
User’s profession (e.g., “Biotechnologist”, “Chemical Engineer”). Required for all employees.
avatar (optional)
avatar (optional)
URL to user’s profile picture. Can be uploaded or set to a default.
isActive (optional)
isActive (optional)
Account status flag. Inactive users cannot log in.
organizationId (optional)
organizationId (optional)
Foreign key linking employees to their organization. Used for organization-managed accounts.
verificationToken (optional)
verificationToken (optional)
Token for email verification flow. Set on registration, cleared on verification.
Account table
Session table
Session configuration
- Expiry: 7 days (604,800 seconds)
- Update age: Sessions refresh after 1 day of activity
- Cookie cache: 5-minute cache for session cookies to reduce DB queries
Verification table
Application tables
Waitlist table
lib/db/migrations/001_waitlist.sql
Schema best practices
Primary keys
Primary keys
Uses
Lowercase identifiers
Lowercase identifiers
All table and column names use snake_case for consistency with PostgreSQL conventions.
Indexes
Indexes
waitlist_email_idx: Fast lookups and UNIQUE constraint enforcementwaitlist_role_idx: Filter by role in admin dashboards
Unique constraints
Unique constraints
Email uniqueness prevents duplicate signups. API returns 409 Conflict on violation (error code 23505).
Migrations
Database migrations are stored inlib/db/migrations/ and applied manually:
Migration tracking
Migrations are tracked in amigrations table:
Environment variables
.env.local
Query patterns
Using the connection pool
Error handling
Best practices
- Use parameterized queries (
$1,$2) to prevent SQL injection - Create indexes on columns used in WHERE clauses and JOINs
- Use
RETURNING *to get inserted/updated rows without additional queries - Handle PostgreSQL error codes (e.g.,
23505for unique violations) - Keep migrations idempotent with
IF NOT EXISTSandWHERE NOT EXISTS - Use
snake_casefor database identifiers,camelCasein TypeScript