---
type: operations guide
title: Database Migrations
description: Guide to managing database schema changes using Drizzle ORM, including generating, reviewing, and applying migrations in development and production environments.
tags: [database, migrations, drizzle, schema]
verified:
  - by: openwiki/0.7.2
    at: 2026-10-14T20:42:32.326Z
---

# Database Migrations

This document explains the workflow for managing database schema changes in the OpenWiki system using [Drizzle ORM](https://orm.drizzle.team).

## Migration Setup

The system uses Drizzle Kit for migration management. Configuration is defined in [`/packages/db/drizzle.config.ts`](../packages/db/drizzle.config.ts):

```typescript
import { defineConfig } from "drizzle-kit";
import "varlock/auto-load";

export default defineConfig({
  dbCredentials: {
    url: process.env.DATABASE_URL || "",
  },
  dialect: "postgresql",
  out: "./src/migrations",
  schema: "./src/schema/index.ts",
  schemaFilter: ["public"],
});
```

Key settings:
- **dialect**: PostgreSQL
- **out**: Migration output directory (`./src/migrations`)
- **schema**: Path to the schema definition (`./src/schema/index.ts`)
- **schemaFilter**: Limits migrations to the `public` schema

## Schema Definition

Database schemas are defined in TypeScript files under [`/packages/db/src/schema/`](/packages/db/src/schema). The main entry point is [`/packages/db/src/schema/index.ts`](../packages/db/src/schema/index.ts), which re-exports all schema definitions.

## Migration Workflow

### 1. Generate a Migration

After modifying the schema, generate a migration script:

```bash
bun run db:generate
```

This command:
- Compares the current schema with the previous state
- Generates a new SQL migration file in `/packages/db/src/migrations/`
- Names the file with a timestamp and description (e.g., `20240101000000_add_user_table.ts`)

### 2. Review the Migration

Inspect the generated migration file to ensure it accurately reflects the intended schema changes. The file contains:
- `up` function: SQL statements to apply the migration
- `down` function: SQL statements to rollback the migration (if supported)

### 3. Apply the Migration Locally

Run the migration against the local development database:

```bash
bun run db:migrate
```

This executes all pending migrations in order, updating the database schema and recording the migration in the `_migrations` table.

### 4. Apply the Migration in Production

The same migration command is used in production environments:

```bash
bun run db:migrate
```

Ensure the `DATABASE_URL` environment variable points to the production database before running.

## Alternative: db:push

For rapid prototyping, the system supports pushing schema changes directly without generating migration files:

```bash
bun run db:push
```

**Warning**: This method bypasses versioned migrations and is **not recommended for production** as it does not create reproducible, auditable schema change records.

## Database Studio

Inspect and interact with the database using Drizzle Studio:

```bash
bun run db:studio
```

This provides a web UI for viewing and editing data, useful during development.

## Best Practices

1. **Always generate migrations** for production schema changes to maintain a versioned history.
2. **Review generated migrations** before applying, especially for complex changes like column renames or data migrations.
3. **Test migrations** on a copy of production data before deploying.
4. **Keep migrations immutable** once applied; never modify an existing migration file.
5. **Use the down function** for rollbacks during development, but note that production rollbacks should be handled with forward-migration fixes when possible.
6. **Coordinate schema changes** with code deployments to ensure compatibility.

## Troubleshooting

### Migration Fails to Apply

- Check the error message for SQL syntax issues or constraint violations.
- Verify the database connection string is correct.
- Ensure no other processes are holding locks on the database.

### Schema Drift

If the database schema diverges from the migration history:
1. Use `db:push` to synchronize (in development only).
2. Or, manually adjust the schema and generate a new migration to capture the difference.

### Missing Migration Table

If the `_migrations` table is missing, run `db:migrate` to create it and apply all pending migrations.

## Related Documentation

- [Database Setup](/setup)
- [Database Systems Overview](/systems/database)
- [Schema Definition](/systems/database#schema-definition)