Skip to main content
AC
Architecture5.3 KBMIT licensed

deprecation-and-migration

Rewritten from patterns in Addy Osmani's agent-skills (MIT)

Plan and execute the removal of old systems, APIs, or features and migrate consumers safely to replacements. Use when sunsetting a feature, replacing a library or service, consolidating duplicate implementations, or deciding whether to maintain or kill legacy code. Not for recording the decision rationale: use documentation-and-adrs. Not for reviewing the replacement's code quality: use a code review skill.

  • deprecation
  • and
  • migration

SKILL.md

Deprecation and Migration

Code is a liability, not an asset. Every line costs maintenance, patches, and onboarding overhead, so code that no longer earns its keep gets removed. Hyrum's Law makes this hard: with enough users, every observable behavior gets depended on, so deprecation requires active migration, not an announcement.

The Deprecation Decision

Answer these five before deprecating anything:

  1. Does the system still provide unique value? Yes: maintain it. No: proceed.
  2. How many consumers depend on it? Quantify with metrics, logs, and dependency analysis.
  3. Does a replacement exist? No: build it first. Never deprecate without an alternative.
  4. What does migration cost each consumer? Trivially automatable: do it. Manual and heavy: weigh against maintenance cost.
  5. What does NOT deprecating cost? Security exposure, engineer time, complexity tax.

Then pick the mode. Advisory: warnings, docs, users migrate on their own timeline. Default to this. Compulsory: hard removal date, required when security risk or maintenance cost justifies forcing it, and only valid if you ship migration tooling, docs, and support with the deadline.

Migration Workflow

  1. Build the replacement. It must cover all critical use cases of the old system, have docs and a migration guide, and be proven in production, not just theoretically better.
  2. Announce and document. Publish a deprecation notice: status and date, replacement, removal date or "advisory", reason, and a concrete step-by-step migration guide. Read references/patterns.md when writing the notice; it has the template.
  3. Migrate incrementally. One consumer at a time: identify touchpoints, switch to the replacement, verify behavior matches, remove old references, confirm no regressions. The Churn Rule: if you own the infrastructure being deprecated, you migrate your users or ship backward-compatible updates. Announcing and walking away is not deprecation, it is abandonment.
  4. Remove. Only after verified zero active usage: delete the code, its tests, docs, config, and finally the deprecation notices themselves.

For the strangler, adapter, and feature-flag migration patterns with code shapes: read references/patterns.md when choosing how to run old and new in parallel.

Zombie Code

Code nobody owns but everybody depends on: no commits in months with active consumers, no maintainer, failing tests nobody fixes, vulnerable dependencies. Zombie code gets one of two outcomes, an assigned owner with real maintenance, or a deprecation plan. Limbo is not an option.

Verification

Before removal, measure usage: check metrics, access logs, and run a repo-wide search for imports and references to the old system. Expect zero active consumers and zero code references. If usage is not zero, you are not done migrating; removal now is an outage, go back to step 3.

After removal, run the full build and test suite. Expect green. If anything breaks, a hidden consumer existed; restore, find it, migrate it.

Good vs Bad

Judgment call: a team wants to sunset an internal API "next quarter".

Bad: Send an email announcing the removal date and mark the endpoints deprecated. Consumers ignore it, the date slips forever, or removal day becomes an incident.

Good: Inventory the 9 consuming services from gateway logs, ship an adapter plus a migration guide, migrate the 3 you own, open PRs for 4 more, escalate the last 2 with the deadline, and remove only when the logs read zero for two weeks.

Footguns

  • Deprecating with no replacement. Users cannot move to nothing, so nothing moves. Fix: replacement first, proven in production.
  • Trusting the announcement. "Users will migrate on their own." They will not. Fix: tooling, incentives, or do the migration yourself.
  • Keeping the old system "just in case". Two systems doing one job doubles maintenance, tests, and onboarding forever. Fix: compare 2-3 years of dual maintenance cost against a rebuild; the rebuild is almost always cheaper.
  • Adding features to a deprecated system. Every addition deepens the hole and signals the deprecation is not real. Fix: hard feature freeze on deprecation day, invest in the replacement only.
  • Removing based on "nobody uses this, probably". Fix: metrics and logs, not vibes, and a search for stragglers before deletion.

Completion Checklist

  • [ ] Five decision questions answered, mode (advisory/compulsory) chosen deliberately
  • [ ] Replacement production-proven and covering all critical use cases
  • [ ] Migration guide published with concrete steps
  • [ ] Zero active usage verified by metrics and repo search before removal
  • [ ] Old code, tests, docs, config, and deprecation notices all removed
  • [ ] Full suite green after removal

Any box unchecked: not done. Fix or say so.

Reference files

More in Architecture

All skills