db-migrations
Database migration guide. Use when generating migrations, writing migration SQL, or modifying database schemas. Triggers on migration generation, schema changes, or idempotent SQL questions.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install lobehub-lobehub-db-migrations
Repository
Skill path: .agents/skills/db-migrations
Database migration guide. Use when generating migrations, writing migration SQL, or modifying database schemas. Triggers on migration generation, schema changes, or idempotent SQL questions.
Open repositoryBest for
Primary workflow: Write Technical Docs.
Technical facets: Full Stack, Backend, Tech Writer.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: lobehub.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install db-migrations into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/lobehub/lobehub before adding db-migrations to shared team environments
- Use db-migrations for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: db-migrations
description: Database migration guide. Use when generating migrations, writing migration SQL, or modifying database schemas. Triggers on migration generation, schema changes, or idempotent SQL questions.
---
# Database Migrations Guide
## Step 1: Generate Migrations
```bash
bun run db:generate
```
This generates:
- `packages/database/migrations/0046_meaningless_file_name.sql`
And updates:
- `packages/database/migrations/meta/_journal.json`
- `packages/database/src/core/migrations.json`
- `docs/development/database-schema.dbml`
## Custom Migrations (e.g. CREATE EXTENSION)
For migrations that don't involve Drizzle schema changes (e.g. enabling PostgreSQL extensions), use the `--custom` flag:
```bash
bunx drizzle-kit generate --custom --name=enable_pg_search
```
This generates an empty SQL file and properly updates `_journal.json` and snapshot. Then edit the generated SQL file to add your custom SQL:
```sql
-- Custom SQL migration file, put your code below! --
CREATE EXTENSION IF NOT EXISTS pg_search;
```
**Do NOT manually create migration files or edit `_journal.json`** — always use `drizzle-kit generate` to ensure correct journal entries and snapshots.
## Step 2: Optimize Migration SQL Filename
Rename auto-generated filename to be meaningful:
`0046_meaningless_file_name.sql` → `0046_user_add_avatar_column.sql`
## Step 3: Use Idempotent Clauses (Defensive Programming)
Always use defensive clauses to make migrations idempotent (safe to re-run):
### CREATE TABLE
```sql
-- ✅ Good
CREATE TABLE IF NOT EXISTS "agent_eval_runs" (
"id" text PRIMARY KEY NOT NULL,
"name" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
-- ❌ Bad
CREATE TABLE "agent_eval_runs" (...);
```
### ALTER TABLE - Columns
```sql
-- ✅ Good
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "avatar" text;
ALTER TABLE "posts" DROP COLUMN IF EXISTS "deprecated_field";
-- ❌ Bad
ALTER TABLE "users" ADD COLUMN "avatar" text;
```
### ALTER TABLE - Foreign Key Constraints
PostgreSQL has no `ADD CONSTRAINT IF NOT EXISTS`. Use `DROP IF EXISTS` + `ADD`:
```sql
-- ✅ Good: Drop first, then add (idempotent)
ALTER TABLE "agent_eval_datasets" DROP CONSTRAINT IF EXISTS "agent_eval_datasets_user_id_users_id_fk";
ALTER TABLE "agent_eval_datasets" ADD CONSTRAINT "agent_eval_datasets_user_id_users_id_fk"
FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
-- ❌ Bad: Will fail if constraint already exists
ALTER TABLE "agent_eval_datasets" ADD CONSTRAINT "agent_eval_datasets_user_id_users_id_fk"
FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
```
### DROP TABLE / INDEX
```sql
-- ✅ Good
DROP TABLE IF EXISTS "old_table";
CREATE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email");
CREATE UNIQUE INDEX IF NOT EXISTS "users_email_unique" ON "users" USING btree ("email");
-- ❌ Bad
DROP TABLE "old_table";
CREATE INDEX "users_email_idx" ON "users" ("email");
```
## Step 4: Regenerate Client After SQL Edits
After modifying the generated SQL (e.g., adding `IF NOT EXISTS`), regenerate the client:
```bash
bun run db:generate:client
```