Help us improve
Share bugs, ideas, or general feedback.
From a-team
Enforces a hard gate for production database schema changes and data transformations. Requires written migration plans with rollback strategies, dry runs, and verification steps to prevent data loss and downtime.
npx claudepluginhub rbraga01/a-team --plugin a-teamHow this skill is triggered — by the user, by Claude, or both
Slash command
/a-team:data-migrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
EVERY MIGRATION NEEDS A ROLLBACK.
A migration without a rollback plan is a one-way door.
Before you open it, know how to close it.
Use this skill before:
ALTER TABLE in productionUPDATE or DELETE (more than 1000 rows)| Type | Risk | Strategy |
|---|---|---|
| Additive (new table, new nullable column) | Low | Single deploy |
| Non-breaking change (add index, add constraint) | Low–Medium | Verify impact first |
| Column rename or type change | High | Multi-phase deploy |
| Column or table removal | High | Multi-phase deploy |
| Large data backfill (>100k rows) | Medium | Batched, off-peak |
| Destructive (DROP TABLE, DELETE) | Critical | Backup + explicit approval |
Save to docs/migrations/YYYY-MM-DD-description.md:
# Migration: [Title]
## Summary
[What changes and why]
## Risk Level
[Low / Medium / High / Critical]
## Migration Steps
### UP (apply)
\```sql
-- Step 1: Add new column (nullable — safe, no lock)
ALTER TABLE orders ADD COLUMN discount_amount NUMERIC(10,2);
-- Step 2: Backfill (batched — see script)
-- Run: scripts/migrations/backfill-discount.sql
-- Step 3: Add NOT NULL constraint after backfill
ALTER TABLE orders ALTER COLUMN discount_amount SET NOT NULL;
\```
### DOWN (rollback)
\```sql
ALTER TABLE orders DROP COLUMN IF EXISTS discount_amount;
\```
## Rollback Plan
[How to revert if something goes wrong — step by step]
## Estimated Duration
[How long will the migration take? Any locking risk?]
## Verification
- [ ] Row count before: SELECT COUNT(*) FROM orders;
- [ ] Row count after matches
- [ ] Sample rows spot-checked: SELECT * FROM orders LIMIT 10;
- [ ] Application queries tested against migrated schema
- [ ] No errors in application logs after deploy
Column rename — never rename directly; multi-phase:
Phase 1: Add new column (old and new both exist)
Phase 2: Deploy app that writes to BOTH columns, reads from old
Phase 3: Backfill new column from old
Phase 4: Deploy app that writes to BOTH, reads from new
Phase 5: Drop old column
Type change — same multi-phase approach; never ALTER COLUMN TYPE on large tables in production directly.
Index creation on large table — always CREATE INDEX CONCURRENTLY:
-- [INVALID] — takes full table lock
CREATE INDEX idx_orders_user ON orders(user_id);
-- [VALID] — non-blocking on PostgreSQL
CREATE INDEX CONCURRENTLY idx_orders_user ON orders(user_id);
Large backfill — never in one transaction; batch it:
-- Process in batches of 1000 rows until done
DO $$
DECLARE
batch_size INT := 1000;
rows_updated INT;
BEGIN
LOOP
UPDATE orders
SET discount_amount = 0
WHERE discount_amount IS NULL
LIMIT batch_size;
GET DIAGNOSTICS rows_updated = ROW_COUNT;
EXIT WHEN rows_updated = 0;
PERFORM pg_sleep(0.1); -- yield between batches
END LOOP;
END $$;
Before executing in production:
# Dry run first (PostgreSQL)
psql $DATABASE_URL --dry-run -f migration.sql
# Real run with timing
psql $DATABASE_URL -f migration.sql --echo-all
# Check for locks during execution
SELECT pid, query, state, wait_event_type, wait_event
FROM pg_stat_activity
WHERE state != 'idle';
-- Row count matches expectations
SELECT COUNT(*) FROM affected_table;
-- Sample spot-check
SELECT * FROM affected_table LIMIT 20;
-- No NULL where NOT NULL expected
SELECT COUNT(*) FROM affected_table WHERE new_column IS NULL;
-- No application errors in logs for 10 minutes post-migration
Migration complete?
└── No errors in monitoring for 10 minutes? → DONE
└── Errors found?
├── Can app tolerate the error state? → Fix forward (hotfix)
└── Cannot tolerate? → ROLLBACK IMMEDIATELY
├── Run DOWN migration
├── Verify application recovers
└── Document in post-mortem