Database Health

CRITICAL RULES

  1. NEVER run drizzle-kit push — it mutates the database directly, bypassing migration files. Always use bunx drizzle-kit generate to create migration SQL, then let the Vercel build step apply it.
  2. NEVER run DDL (ALTER TABLE, DROP, CREATE TABLE) directly against any shared Neon branch.
  3. NEVER edit or reorder files in drizzle/ — the migration journal tracks sequence. If you need to fix a migration, generate a new corrective one.
  4. ALWAYS check which branch you're connected to before any database operation.

Quick Health Check

Run the full health check:

./scripts/db-health.sh

This validates: connection string, Neon branch, drizzle-kit check, migration journal integrity, and table count.

Branch Check

Before any database work, confirm your target:

./scripts/db-branch-check.sh

This script will fail with exit code 1 if you're connected to production (Neon main branch) unless you pass --allow-production.

Known Endpoints

EndpointBranchEnvironment
ep-rapid-pond-akug8qa3mainPRODUCTION
ep-restless-moon-akqogjx1stagingPreview/Development

If the endpoint is unknown, the script uses the Neon API (NEON_API_KEY) to resolve it.

Schema Change Workflow

  1. Edit lib/schema.ts
  2. Run ./scripts/db-branch-check.sh — confirm you're NOT on production
  3. Generate migration: bunx drizzle-kit generate
  4. Validate: bun run db:check
  5. Review the generated SQL in drizzle/NNNN_*.sql
  6. Run full health check: ./scripts/db-health.sh
  7. Commit the migration files alongside the schema change

Never apply migrations manually. The Vercel build step runs migrations automatically using DATABASE_URL_UNPOOLED (direct connection, not pooled).

Pooled vs Unpooled URLs

  • DATABASE_URLpooled (via pgbouncer). Use for runtime queries. Cannot run DDL.
  • DATABASE_URL_UNPOOLEDdirect. Used by Drizzle migrations at build time. Required for DDL.

Both must point at the same Neon branch.

The Staging-as-Default Quirk

The Neon-Vercel integration uses the Neon default branch for production. We set staging as default so preview branches fork from staging data. This means the integration sets Production DATABASE_URL to the wrong endpoint. Production DATABASE_URL must be set manually. See ENVIRONMENT.md for the full matrix.

Neon Project Details

  • Project ID: solitary-tooth-56221123
  • Region: aws-us-west-2
  • API: NEON_API_KEY in GitHub org secrets

If You're Lost