09 - Migrations
📋 Jump to TakeawaysDrizzle Kit handles schema changes. It reads your TypeScript schema, compares it to the database, and generates SQL migration files. You choose between push for quick iteration and migrate for production safety.
Drizzle Config
Every project needs a drizzle.config.ts at the root.
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/db/schema.ts',
out: './drizzle',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!
}
});schema points to your table definitions. out is where migration files go. dialect matches your database.
Push vs Migrate
These are two different workflows. Pick one based on your situation.
Push
drizzle-kit push applies your schema directly to the database. No migration files. Fast and simple.
npx drizzle-kit pushUse push during local development when you are iterating on your schema and do not need a history of changes.
Migrate
drizzle-kit generate creates SQL migration files. drizzle-kit migrate runs them in order.
# Generate a migration from schema changes
npx drizzle-kit generate
# Apply pending migrations
npx drizzle-kit migrateUse migrate in production. Migration files give you a versioned history, code review on schema changes, and rollback points.
❌ Using push in production:
# Dangerous: no history, no review, can drop data
npx drizzle-kit push✅ Using generate + migrate in production:
npx drizzle-kit generate
# Review the generated SQL file
npx drizzle-kit migrateMigration Files
Generated migrations live in your out directory. Each file has a timestamp and a SQL file.
drizzle/
├── 0000_initial.sql
├── 0001_add_posts_table.sql
├── 0002_add_user_role.sql
└── meta/
└── _journal.jsonThe _journal.json tracks which migrations have run. Never edit it manually.
A migration file looks like plain SQL:
ALTER TABLE "users" ADD COLUMN "role" text DEFAULT 'user' NOT NULL;Drizzle Studio
drizzle-kit studio opens a browser UI to view and edit your data.
npx drizzle-kit studioUseful for inspecting data during development. Not a production tool.
Safe Schema Changes
Some changes are safe. Others can destroy data. Know the difference.
Adding a column
Safe. Add a default value to avoid breaking existing rows.
// In your schema
role: text('role').default('user').notNull()npx drizzle-kit generate
# Generated SQL: ALTER TABLE "users" ADD COLUMN "role" text DEFAULT 'user' NOT NULL;Renaming a column
Drizzle Kit may interpret a rename as a drop + add, which deletes data. Check the generated SQL carefully.
-- What you might expect:
ALTER TABLE "users" RENAME COLUMN "name" TO "full_name";
-- What Drizzle Kit might generate:
ALTER TABLE "users" DROP COLUMN "name";
ALTER TABLE "users" ADD COLUMN "full_name" text;If the generated SQL drops and adds, edit the migration file manually to use RENAME COLUMN instead.
Dropping a column
Permanent data loss. Always back up first.
npx drizzle-kit generate
# Review the SQL before running
cat drizzle/0003_drop_legacy_field.sql
npx drizzle-kit migratePractical Workflow
A typical development cycle:
- Edit your schema in TypeScript
- Run
npx drizzle-kit pushlocally to test - When ready, run
npx drizzle-kit generateto create a migration - Review the generated SQL
- Commit the migration file
- In production, run
npx drizzle-kit migrate
# Local development
npx drizzle-kit push
# Ready for production
npx drizzle-kit generate
git add drizzle/
git commit -m "add role column to users"
# Production deploy
npx drizzle-kit migrateKey Takeaways
drizzle.config.tsdefines your schema path, output directory, dialect, and database credentialspushapplies schema directly; use it for local development onlygeneratecreates versioned SQL files;migrateruns them in order- Always review generated SQL before applying, especially for renames and drops
- Migration files are plain SQL and can be edited manually when needed
drizzle-kit studioprovides a visual data browser for development- Never edit
_journal.jsonmanually