Files
agent-skills/skills/safe-deprecation-and-migration/SKILL.md
T

80 lines
3.5 KiB
Markdown

---
name: safe-deprecation-and-migration
description: Use when replacing or retiring an API, feature, dependency, service, or database schema. Plans measured, reversible migrations with compatibility periods, incremental consumer cutover, expand-contract data changes, and verified removal.
license: MIT
source: adapted from https://github.com/addyosmani/agent-skills/tree/main/skills/deprecation-and-migration (MIT)
---
# Safe Deprecation and Migration
Treat removal as a migration, not a deletion. Do not announce a replacement
until it covers critical use cases and do not remove the old path until measured
usage reaches zero.
## Decide with evidence
Before changing anything, inventory:
- the old system's unique value and current owner;
- all known consumers and touchpoints (code, jobs, configs, docs, data);
- usage from logs/metrics, including a time window that covers infrequent jobs;
- undocumented behavior consumers may rely on;
- replacement readiness and per-consumer migration cost;
- maintenance, security, and opportunity cost of keeping both paths.
Choose advisory deprecation when the old system remains safe and supportable.
Use a compulsory deadline only when risk or maintenance cost justifies it, and
pair it with tooling, documentation, ownership, and support.
## Build the migration plan
Define these before cutover:
1. Replacement behavior and known gaps.
2. Compatibility mechanism: adapter, dual-read/write, feature flag, or traffic
splitting.
3. Consumer-by-consumer order, owner, and completion signal.
4. Observability that distinguishes old and new usage and compares outcomes.
5. Advance, hold, rollback, and final-removal criteria.
6. Exact rollback actions, including what happens to data written by the new
path.
Migrate one bounded cohort or consumer at a time. Verify behavior and telemetry
before expanding. Prefer owning teams to migrate their consumers or provide an
automatic compatibility layer; a warning alone is not a migration.
## Use expand-contract for data shapes
Never rename or drop a live field/column in the same release that changes the
code using it. Use separately deployable phases:
1. **Expand:** add the new nullable shape alongside the old one.
2. **Dual-write:** populate both shapes for new changes.
3. **Backfill:** migrate existing data in throttled, restartable batches.
4. **Switch reads:** read the new shape while continuing dual writes; bake and
compare results.
5. **Contract:** stop old writes, prove no reads remain, then drop the old shape
in a later release.
Make every phase safe while old and new application versions coexist. For large
tables, avoid long locks; use the datastore's online/concurrent mechanisms.
Design and test the down path before merging. If a data transformation is not
reversible, state that explicitly and use backups/checkpoints plus a forward
repair plan instead of pretending a code rollback restores data.
## Remove completely
Only remove the old path after telemetry shows zero use for the agreed window
and every consumer is signed off. Then remove its code, flags, adapters, tests,
configuration, dashboards, alerts, and obsolete documentation together.
Verify afterward:
- no code/config/doc references remain;
- the replacement handles production traffic normally;
- rollback or forward-repair remains available through the observation window;
- temporary compatibility logic and dual writes are gone.
Do not let a supposedly temporary adapter or feature flag become a permanent
second system: assign an owner and expiry date when creating it.