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

3.5 KiB

name, description, license, source
name description license source
safe-deprecation-and-migration 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. MIT 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.