Database Requirements
The application requires:- PostgreSQL 12 or higher (PostgreSQL 18 recommended)
- A database with connection credentials
- Network access from your application to the database
Setup Options
You can set up PostgreSQL in two ways:Option 1: Dev Container (Recommended)
The Dev Container setup includes PostgreSQL 18 automatically configured and ready to use.Install Prerequisites
Open in Dev Container
- Open the project in VS Code
- Press
Cmd+Shift+P(Mac) orCtrl+Shift+P(Windows/Linux) - Select “Dev Containers: Reopen in Container”
- Wait for the container to build (first time takes a few minutes)
Option 2: Manual PostgreSQL Installation
If you prefer to run PostgreSQL locally without Docker:Install PostgreSQL
Create Database and User
Connect to PostgreSQL and create a database:Run these SQL commands:
Replace
myapp, myapp_user, and secure_password with your preferred values.Connection String Format
TheDATABASE_URL environment variable uses the standard PostgreSQL connection string format:
| Component | Description | Example |
|---|---|---|
username | Database user | postgres, myapp_user |
password | User password | postgres, secure_password |
host | Database server hostname or IP | localhost, postgres, db.example.com |
port | PostgreSQL port (default: 5432) | 5432 |
database | Database name | postgres, myapp |
Database Schema
The database schema is defined insrc/db/schema.ts using Drizzle ORM. Better Auth automatically manages five tables:
Tables Overview
| Table | Purpose |
|---|---|
user | User profiles and account information |
session | Active authentication sessions |
account | OAuth provider links and credentials |
verification | Email verification tokens |
jwks | JSON Web Key Sets for JWT signing |
User Table
Stores core user profile information:src/db/schema.ts
id- Unique user identifier (text UUID)name- User’s display nameemail- Email address (unique)emailVerified- Whether email has been verified (boolean)image- Profile picture URL (from OAuth providers)createdAt- Account creation timestampupdatedAt- Last update timestamp
Session Table
Tracks active user sessions:src/db/schema.ts
id- Session identifierexpiresAt- When the session expirestoken- Session token (unique, used in cookies)ipAddress- IP address of the clientuserAgent- Browser user agent stringuserId- Foreign key tousertable (cascading delete)
Account Table
Links OAuth provider accounts to users:src/db/schema.ts
id- Account record identifieraccountId- Provider-specific user ID (e.g., Google user ID)providerId- Provider name (“google”, “github”, “email”, etc.)userId- Foreign key tousertableaccessToken- OAuth access token (for API calls)refreshToken- OAuth refresh token (for renewing access)idToken- OAuth ID token (JWT with user claims)password- Hashed password (for email/password auth)scope- OAuth scopes granted
Verification Table
Stores temporary verification tokens:src/db/schema.ts
JWKS Table
Stores cryptographic keys for JWT signing:src/db/schema.ts
/api/auth/jwks for backend services to verify tokens.
Database Operations
The boilerplate includes several npm scripts for managing your database:Initial Setup
After configuring yourDATABASE_URL, push the schema to create all tables:
db:push is great for development. For production, use db:generate and db:migrate to create proper migration files.Adding Custom Tables
To add your own tables to the schema:Drizzle Configuration
The database configuration is defined indrizzle.config.ts:
drizzle.config.ts
schema- Path to your schema definitionout- Where to store migration filesdialect- Database type (“postgresql”)dbCredentials.url- Connection string from environment
Connection Pool
The database connection is established insrc/db/index.ts:
src/db/index.ts
Troubleshooting
”Connection refused” Error
Symptom: Application crashes withECONNREFUSED error.
Solutions:
- Verify PostgreSQL is running:
pg_isready(manual install) or check Docker containers (Dev Container) - Check the
hostin yourDATABASE_URLmatches where PostgreSQL is running - For Dev Container, use
postgresas the host, notlocalhost - For local PostgreSQL, use
localhostor127.0.0.1
”Password authentication failed”
Symptom: Database connection fails with authentication error. Solutions:- Double-check the username and password in
DATABASE_URL - Ensure no extra spaces or special characters need URL encoding
- For manual PostgreSQL, verify user exists:
psql -U postgres -c "\du"
”Database does not exist”
Symptom: Connection fails with database not found error. Solutions:- Create the database:
createdb myappor use SQL:CREATE DATABASE myapp; - Verify the database name in
DATABASE_URLmatches the actual database
Tables Not Created
Symptom:npm run db:push succeeds but tables aren’t visible.
Solutions:
- Check that
DATABASE_URLpoints to the correct database - View tables with:
psql $DATABASE_URL -c "\dt" - Verify the schema file has no syntax errors
”SSL Connection Required”
Symptom: Production database requires SSL but connection fails. Solution: Addsslmode=require to your connection string:
Viewing Database Contents
Option 1: Drizzle Studio (Recommended)https://local.drizzle.studio
Option 2: psql CLI
DATABASE_URL credentials.
Production Considerations
Connection Pooling
For serverless environments (Vercel, AWS Lambda), use connection pooling:SSL/TLS
Always use SSL for production databases:Backups
Set up automated backups:- Most managed PostgreSQL services (AWS RDS, Google Cloud SQL, Supabase) include automatic backups
- For self-hosted, use
pg_dumpwith cron jobs
Migrations
Use migrations instead ofdb:push in production:
Related Documentation
- Environment Variables -
DATABASE_URLconfiguration reference - Google OAuth Setup - Understanding the account linking tables