database/writing-migrations/SKILL.md
Create and manage Alembic database migrations with safe upgrade and downgrade paths.
npx skillsauth add 7a336e6e/skills Writing MigrationsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate reliable, reversible Alembic migrations that evolve the database schema incrementally. Every migration must include both an upgrade and a downgrade path, and must be reviewed before being applied.
Use Alembic's autogenerate feature as a starting point, then review and edit the output.
alembic revision --autogenerate -m "add status column to tasks"
This creates a file like 20250115_143022_add_status_column_to_tasks.py. The naming convention is: timestamp prefix followed by an imperative description of the change.
Never trust autogenerate blindly. It may miss certain changes or produce incorrect operations. Always open the generated file and verify:
A well-structured migration includes both upgrade() and downgrade() functions.
"""add status column to tasks
Revision ID: a1b2c3d4e5f6
Revises: f6e5d4c3b2a1
Create Date: 2025-01-15 14:30:22.000000
"""
from alembic import op
import sqlalchemy as sa
revision = "a1b2c3d4e5f6"
down_revision = "f6e5d4c3b2a1"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"tasks",
sa.Column(
"status",
sa.String(length=20),
nullable=False,
server_default="pending",
),
)
op.create_index("ix_tasks_status", "tasks", ["status"])
def downgrade() -> None:
op.drop_index("ix_tasks_status", table_name="tasks")
op.drop_column("tasks", "status")
Schema migrations change structure. Data migrations change content. Keep them in separate migration files to maintain clarity and reversibility.
# Schema migration: add the column
def upgrade() -> None:
op.add_column("users", sa.Column("full_name", sa.String(200), nullable=True))
# Separate data migration: populate the column
def upgrade() -> None:
op.execute(
"UPDATE users SET full_name = display_name WHERE full_name IS NULL"
)
After the data migration, create a third migration to add the NOT NULL constraint if needed.
Always test both directions before merging:
# Apply the migration
alembic upgrade head
# Verify the schema change
# ...
# Roll back the migration
alembic downgrade -1
# Verify clean rollback
# ...
# Re-apply for final state
alembic upgrade head
def upgrade() -> None:
op.alter_column("tasks", "name", new_column_name="title")
def downgrade() -> None:
op.alter_column("tasks", "title", new_column_name="name")
def upgrade() -> None:
# Step 1: Add as nullable with a default
op.add_column("tasks", sa.Column("priority", sa.Integer(), nullable=True))
# Step 2: Backfill existing rows
op.execute("UPDATE tasks SET priority = 0 WHERE priority IS NULL")
# Step 3: Set NOT NULL
op.alter_column("tasks", "priority", nullable=False)
def downgrade() -> None:
op.drop_column("tasks", "priority")
Produce an Alembic migration Python file with the standard header (revision, down_revision, description), an upgrade() function, and a downgrade() function. Include inline comments explaining non-obvious operations.
development
Implement features using the Red-Green-Refactor cycle to ensure testability and correctness from the start.
data-ai
Manage the `tasks.md` ledger with strict locking and collision avoidance protocols to allow multiple agents to work in parallel safely.
development
The git-workflow skill defines branching conventions, commit message formats, and pull request standards that all agents must follow for consistent version control.
development
The environment-config skill standardizes how agents manage environment variables, secrets, and application configuration across local development and deployed environments.