skills/database-migration-planner/SKILL.md
Plan database migrations before executing them: risk assessment, dependency mapping, multi-service sequencing, rollback budgets, and stakeholder communication plans. Use when deciding HOW to migrate, not when writing the actual DDL. NOT for: writing migration SQL (use database-migration-manager), data ETL pipelines (use data-migration-specialist), query optimization, or ORM configuration.
npx skillsauth add curiositech/windags-skills database-migration-plannerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Plans safe, sequenced database migrations before any SQL is written. Produces migration plans with risk scores, dependency graphs, rollback budgets, and communication timelines.
✅ Use for: Deciding migration strategy, risk-scoring schema changes, sequencing migrations across multiple services, estimating rollback windows, planning communication to dependent teams, assessing lock contention risk, choosing between expand-contract vs. blue-green vs. big-bang.
❌ NOT for: Writing DDL/migration files (→ database-migration-manager), executing data pipelines (→ data-migration-specialist), query performance (→ postgresql-optimization), ORM config (→ drizzle-migrations).
flowchart TD
A[Describe the change] --> B{Single service?}
B -->|Yes| C[Assess risk level]
B -->|No| D[Map service dependencies]
D --> E[Determine migration order]
E --> C
C --> F{Risk level}
F -->|Low: additive only| G[Direct migration plan]
F -->|Medium: modify existing| H[Expand-contract plan]
F -->|High: destructive or cross-service| I[Phased rollout plan]
G --> J[Estimate rollback budget]
H --> J
I --> J
J --> K[Communication plan]
K --> L[Final migration plan document]
| Risk Level | Characteristics | Strategy | Rollback Budget | |-----------|----------------|----------|-----------------| | Low | Additive only (new table, new nullable column, new index on small table) | Direct apply | Minutes | | Medium | Modifies existing (column type change, NOT NULL addition, index on large table) | Expand-contract | Hours | | High | Destructive (drop column/table, rename across services, data type narrowing) | Phased rollout with feature flags | Days | | Critical | Cross-database, multi-region, or involves PII restructuring | Blue-green database with traffic replay | Weeks |
flowchart TD
Q1{Can old code work with new schema?}
Q1 -->|Yes| Q2{Is the change additive?}
Q1 -->|No| EXPAND[Expand-Contract required]
Q2 -->|Yes| DIRECT[Direct migration]
Q2 -->|No| Q3{Table size > 1M rows?}
Q3 -->|Yes| ONLINE[Online DDL tool required]
Q3 -->|No| EXPAND
EXPAND --> Q4{Multiple services read this table?}
Q4 -->|Yes| PHASED[Phased: migrate consumers first]
Q4 -->|No| SINGLE[Single expand-contract cycle]
flowchart TD
L1{Operation type?}
L1 -->|ADD COLUMN nullable| SAFE[No lock concern]
L1 -->|ADD COLUMN NOT NULL + default| PG{Postgres ≥ 11?}
PG -->|Yes| SAFE
PG -->|No| REWRITE[Full table rewrite - dangerous]
L1 -->|ALTER TYPE| REWRITE
L1 -->|CREATE INDEX| CONC{Use CONCURRENTLY?}
CONC -->|Yes| SAFE
CONC -->|No| BLOCKS[Blocks writes for duration]
L1 -->|DROP COLUMN| SAFE2[Instant in PG, rewrite in MySQL < 8.0]
L1 -->|RENAME| INSTANT[Instant but breaks queries]
Novice: "It's just one ALTER TABLE, ship it directly."
Expert: Risk comes from service coupling and table size, not DDL line count. A single ALTER TABLE ADD COLUMN NOT NULL on a 500M-row table with 12 consuming services is Critical-risk regardless of its syntactic simplicity.
Detection: Plan mentions "simple change" without noting row count or consumer count.
Novice: "We'll figure out rollback if something goes wrong." Expert: Rollback is designed first. Every migration plan starts with: "How do I undo this in under X minutes?" If the answer is "you can't," the migration needs a different strategy (expand-contract, blue-green). Timeline: Pre-2020: rollback was optional for many teams. Post-incident-culture (2020+): rollback budget is a hard requirement.
Novice: Plans migration for primary only. Expert: Read replicas lag. Caches have stale schemas. A migration plan must account for: replica lag window, cache TTL expiry, connection pool recycling, and ORM schema cache invalidation. Miss any one and you get 500s from readers even though the primary migrated cleanly.
When producing a plan, output this structure:
# Migration Plan: [Name]
## Summary
- **Change**: [What's changing]
- **Risk Level**: Low / Medium / High / Critical
- **Estimated Duration**: [Time from start to verified-complete]
- **Rollback Budget**: [Max time to fully reverse]
- **Affected Services**: [List]
## Dependencies
- [ ] Service A must deploy read-compatibility code first
- [ ] Cache TTL must expire (12h) before dropping old column
- [ ] Feature flag `new_schema_v2` must be enabled in staging first
## Sequence
| Step | Action | Duration | Rollback |
|------|--------|----------|----------|
| 1 | Deploy app code that reads both old+new | 30m | Revert deploy |
| 2 | Run forward migration | 5m | Run rollback SQL |
| 3 | Backfill new column from old | 2h | Truncate new column |
| 4 | Verify data integrity | 30m | N/A |
| 5 | Switch reads to new column | 15m | Feature flag off |
| 6 | Remove old column (after bake period) | 1 week | N/A (point of no return) |
## Rollback Plan
- **Trigger**: Error rate > 1% OR p99 latency > 2x baseline
- **Procedure**: [Specific steps]
- **Point of no return**: Step 6 (old column dropped)
## Communication
- [ ] Notify dependent teams 1 week before
- [ ] Post in #migrations channel day-of
- [ ] Update API docs if schema is exposed
When a migration spans multiple services:
sequenceDiagram
participant Writer as Service A (Writer)
participant DB as Database
participant Reader1 as Service B (Reader)
participant Reader2 as Service C (Reader)
Note over Writer,Reader2: Phase 1: Expand
Writer->>Writer: Deploy dual-write code
Writer->>DB: ALTER TABLE ADD new_column
Writer->>DB: Backfill new_column FROM old_column
Note over Writer,Reader2: Phase 2: Migrate Readers
Reader1->>Reader1: Deploy: read from new_column
Reader2->>Reader2: Deploy: read from new_column
Note over Writer,Reader2: Phase 3: Contract (after bake)
Writer->>Writer: Remove old_column writes
Writer->>DB: ALTER TABLE DROP old_column
| Factor | Impact on Duration | |--------|-------------------| | Table rows > 10M | +1h per 100M rows for backfill | | Consuming services > 3 | +1 week bake time per additional service | | PII/compliance columns | +1 week for legal review | | Multi-region database | 2x total duration (replica sync) | | No staging environment | 3x risk score (can't rehearse) | | Active on-call incident | STOP. Do not plan migrations during incidents. |
references/risk-matrix.md — Detailed risk scoring with weighted factors for table size, consumer count, data sensitivity, and region topologyreferences/communication-templates.md — Pre-written Slack/email templates for migration announcements, go/no-go decisions, and incident escalationreferences/platform-quirks.md — Database-specific gotchas: Postgres online DDL limitations, MySQL metadata locks, CockroachDB schema change jobs, PlanetScale branching modeldata-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.