Set up and manage database schema versioning with migration files, automated rollback capabilities, and CI/CD integration. Use when you need to version database changes, generate migration files from schema diffs, safely roll back failed deployments, or audit schema history. Trigger words: migration, schema change, rollback, database versioning, ALTER TABLE, Prisma migrate, Knex migrations, Flyway, Liquibase.
This skill helps you establish a reliable database schema versioning workflow: generating timestamped migration files, testing them against a shadow database, integrating schema checks into CI/CD, and rolling back safely when deployments fail. It works with any migration tool (Prisma, Knex, TypeORM, Flyway, Alembic) and focuses on patterns rather than vendor lock-in.
Set up the migration directory structure and configuration:
# For Knex.js
npx knex init
npx knex migrate:make initial_schema
# For Prisma
npx prisma init
npx prisma migrate dev --name initial_schema
# For Alembic (Python)
alembic init migrations
alembic revision --autogenerate -m "initial_schema"
Create a shadow database for testing migrations before applying to production:
# docker-compose.shadow-db.yml
services:
shadow-db:
image: postgres:16
environment:
POSTGRES_DB: app_shadow
POSTGRES_PASSWORD: shadow_test
ports:
- "5433:5432"
When models change, generate the migration diff:
// Knex migration example: 20250217_add_orders_table.ts
import { Knex } from "knex";
export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable("orders", (table) => {
table.uuid("id").primary().defaultTo(knex.fn.uuid());
table.uuid("user_id").notNullable().references("id").inTable("users");
table.decimal("total", 10, 2).notNullable();
table.enum("status", ["pending", "paid", "shipped", "cancelled"]).defaultTo("pending");
table.timestamps(true, true);
table.index(["user_id", "status"]);
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists("orders");
}
Always test against a shadow database before production:
# Apply all pending migrations to shadow database
DATABASE_URL="postgres://localhost:5433/app_shadow" npx knex migrate:latest
# Verify the migration is reversible
DATABASE_URL="postgres://localhost:5433/app_shadow" npx knex migrate:rollback
# Re-apply to confirm idempotency
DATABASE_URL="postgres://localhost:5433/app_shadow" npx knex migrate:latest
Create a rollback script that handles both schema and data rollbacks:
#!/bin/bash
# rollback.sh — Roll back the last N migrations
set -euo pipefail
ROLLBACK_COUNT=${1:-1}
ENVIRONMENT=${2:-staging}
echo "Rolling back $ROLLBACK_COUNT migration(s) on $ENVIRONMENT..."
# Capture current state for audit
npx knex migrate:currentVersion --env "$ENVIRONMENT" > /tmp/pre_rollback_version.txt
# Execute rollback
npx knex migrate:rollback --count "$ROLLBACK_COUNT" --env "$ENVIRONMENT"
# Verify post-rollback state
npx knex migrate:currentVersion --env "$ENVIRONMENT" > /tmp/post_rollback_version.txt
echo "Rolled back from $(cat /tmp/pre_rollback_version.txt) to $(cat /tmp/post_rollback_version.txt)"
Add migration checks to your pipeline:
# .github/workflows/migration-check.yml
migration-check:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: test_db
POSTGRES_PASSWORD: test
ports: ["5432:5432"]
steps:
- uses: actions/checkout@v4
- run: npm ci
- name: Apply all migrations from scratch
run: npx knex migrate:latest
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/test_db
- name: Verify rollback works
run: npx knex migrate:rollback --all
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/test_db
- name: Re-apply to confirm clean state
run: npx knex migrate:latest
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/test_db
Prompt: "Generate a migration that adds an email_verified boolean column to the users table, defaulting to false, and backfills it to true for all users who have logged in within the last 90 days."
Agent output:
migrations/20250217143000_add_email_verified_to_users.tsup function adds the column with a default, then runs a data backfill query using last_login_at > NOW() - INTERVAL '90 days'down function drops the columnPrompt: "I need to rename the customers table to clients without breaking the app during deployment. Generate a zero-downtime migration strategy."
Agent output:
clients table, add trigger to sync writes from customers to clientscustomers to clientscustomers pointing to clients (backwards compatibility)clientsdown functiondown function — untested rollbacks fail when you need them most.npx skills add TerminalSkills/schema-versioning下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer