Skip to main content
Budgetron uses Drizzle ORM for database management and migrations. This guide covers the migration workflow for local development and production.

Migration Files Location

All migrations are stored in the drizzle/migrations/ directory:

Configuration

Migration settings are defined in drizzle.config.ts:

Database Schema Organization

The database schema is defined in TypeScript files:
  • src/server/db/schema.ts - Central export that combines all schemas
  • src/server/db/schemas/ - Individual table definitions:
    • user.ts, session.ts, account.ts - Authentication
    • bank-account.ts - Bank accounts
    • transaction.ts - Financial transactions
    • category.ts - Categories
    • budget.ts - Budgets
    • currency-rate.ts - Exchange rates
    • group.ts, group-user.ts - Groups
    • user-settings.ts - User settings
    • feature-flags.ts - Feature flags
    • enums.ts - Shared enums

Common Migration Commands

Apply Migrations

Run pending migrations against your database:
This command:
  1. Connects to the database specified in DB_URL
  2. Checks the __drizzle_migrations table
  3. Applies any pending migrations in order

Generate New Migration

After modifying schema files in src/server/db/schemas/, generate a migration:
Drizzle Kit will:
  1. Compare your schema to the current database state
  2. Generate SQL migration files
  3. Update the metadata in drizzle/migrations/meta/
Review the generated SQL before applying it.

Push Schema (Development Only)

For rapid prototyping, push schema changes directly without migrations:
Use with caution: db:push bypasses migration history and can cause data loss. Only use during active development.

Open Drizzle Studio

Explore your database with Drizzle Studio (a visual database browser):
This opens a web interface at http://localhost:4983.

Development Environment Workflow

If you maintain separate .env and .env.development files:

Using Development Environment

These commands use dotenv-cli to load variables from .env.development instead of .env.

Creating Migrations

Step-by-Step Workflow

  1. Modify the schema Edit files in src/server/db/schemas/, for example transaction.ts:
  2. Generate the migration
    Drizzle Kit will prompt you for a migration name or auto-generate one.
  3. Review the migration Check the generated SQL in drizzle/migrations/[number]_[name].sql:
  4. Apply the migration
  5. Commit both the schema and migration files

Patching Migrations

For advanced scenarios, you can patch migrations programmatically:
This runs scripts/db-migrations-patch.ts, which can modify migration files before they’re applied.

Production Migrations

Docker Entrypoint

The Dockerfile includes an entrypoint script that automatically runs migrations on container start:

Manual Production Migrations

If you need to run migrations manually in production:
Or use the standalone migration runner:

Migration Tracking

Drizzle tracks applied migrations in the __drizzle_migrations table: You can query this table to see migration history:

Best Practices

Do:

  • Always generate migrations for schema changes in production
  • Review generated SQL before applying migrations
  • Test migrations on a copy of production data
  • Commit migrations with schema changes in the same PR
  • Use descriptive migration names when prompted
  • Back up production database before major migrations

Don’t:

  • Don’t use db:push in production - it bypasses migration history
  • Don’t edit applied migrations - create a new migration instead
  • Don’t skip migrations - apply them in order
  • Don’t commit schema changes without migrations

Troubleshooting

Migration Already Applied

If you see “Migration already applied”:
  1. Check __drizzle_migrations table
  2. Verify the migration hash matches
  3. If developing locally, consider resetting your database

Migration Failed

If a migration fails mid-execution:
  1. Check PostgreSQL logs for errors
  2. Verify your database user has sufficient permissions
  3. Manually fix the database state if needed
  4. Remove the failed entry from __drizzle_migrations
  5. Re-run the migration

Schema Out of Sync

If your schema doesn’t match the database:
  1. Run pnpm run db:generate to see the diff
  2. Apply with pnpm run db:migrate
  3. Or use pnpm run db:push if in development