migrating-code
Migrating Code
Core Principles
- Never break production - Backward compatible until fully rolled out
- Small, reversible steps - Each step independently deployable
- Test at every stage - Before, during, and after
- Have rollback ready - Always
Migration Checklist
- [ ] Pre-Migration: Read changelog, identify breaking changes, ensure test coverage
- [ ] During: Small steps, test each, monitor errors, rollback ready
- [ ] Post: Verify tests, check metrics, remove scaffolding, update docs
Database Schema
Safe Patterns
| Operation | Pattern |
|---|---|
| Add column | Add nullable first → backfill → add constraints |
| Remove column | Stop writes → deploy code that doesn't read → drop column |
| Rename column | Add new → dual-write → backfill → switch reads → drop old |
| Change type | New column → dual-write → migrate in batches → switch → drop |
Never: Add NOT NULL without defaults to tables with data.
API Migrations
Deprecation Process
- Add deprecation warnings to old endpoints
- Document migration path
- Set and communicate sunset date
- Monitor usage
- Remove after usage drops
{
"data": {},
"_warnings": [{
"code": "DEPRECATED_ENDPOINT",
"message": "Use /api/v2/users instead",
"sunset": "2025-06-01"
}]
}
Framework Upgrades
- Upgrade to latest minor first - Get deprecation warnings
- Fix warnings - Before major upgrade
- One major at a time - Don't batch
- Test after each step
Adapter Pattern for Library Swaps
// Wrap library usage
// lib/date.ts
import moment from 'moment';
export const formatDate = (date: Date, format: string) =>
moment(date).format(format);
// Migration: just change the adapter
import { format } from 'date-fns';
export const formatDate = (date: Date, fmt: string) =>
format(date, fmt);
Gradual Rollout
Use feature flags:
if (featureFlags.useNewSystem) {
return newService.process(order);
} else {
return legacyService.process(order);
}
Roll out: 1% → 10% → 50% → 100% → remove flag
Common Pitfalls
Avoid:
- Big bang migrations
- No rollback plans
- Skipping dual-write phase
- Single large data transactions
- Removing old code before new is proven
Do:
- Small, reversible steps
- Test rollback procedures
- Batch large data migrations
- Keep old paths until new verified
More from rileyhilliard/claude-essentials
design
Enforces precise, minimal design for dashboards and admin interfaces. Use when building SaaS UIs, data-heavy interfaces, or any product needing Jony Ive-level craft.
18writer
Writing style and tone guide for human-sounding content. Use when writing documentation, READMEs, commit messages, PR descriptions, blog posts, or any user-facing content.
16strategy-writer
Produces executive-quality strategic documents in The Economist/HBR style. Use when writing strategy memos, market analysis, business cases, customer research reports, or any document for Product, Design, and Business leaders. Customer-led, evidence-based, narrative-driven.
13executing-plans
Executes implementation plans with smart task grouping. Groups related tasks to share context, parallelizes across independent subsystems.
12refactoring-code
Improves code structure while preserving behavior through test verification. Use when cleaning up code, reducing duplication, simplifying complexity, or reorganizing modules.
12handling-errors
Prevents silent failures and context loss in error handling. Use when writing try-catch blocks, designing error propagation, reviewing catch blocks, or implementing Result patterns.
12