skip to content

A widely-used internal library is being formally deprecated because a better-supported alternative has emerged. Walk through the deprecation lifecycle you'd run so that dozens of dependent teams migrate off it without a disruptive forced cutover.

level: seniorimportance: must knowfreq 60%

answer

  1. announce->deprecate-support->migrate->sunset
  2. lead time scales with migration effort
  3. keep patching during support window
  4. codemods+usage telemetry, not just a guide
  5. narrow documented exceptions, not blanket extension

basics

~20 s

Announce the deprecation early with a clear reason and a replacement, mark the old version as deprecated (warnings, docs) while still supporting it for a while, set a firm but generous sunset date, help teams migrate (tooling, guides, office hours), and only remove or break it after most teams have moved and the deadline has passed — extending only for genuinely blocked cases.

solid answer

~60 s

A healthy deprecation lifecycle has distinct phases: announce (publish the decision, the reason, the replacement, and a target sunset date, giving teams lead time proportional to migration effort); deprecate-but-support (mark the old library as deprecated — compiler/linter warnings, doc banners — while it keeps working and keeps receiving critical security patches, so nobody is forced to stop shipping); migrate (provide a migration guide, codemods or automated tooling where possible, and a tracked list of remaining consumers so the effort is visible, not just a Slack announcement); and sunset (after the deadline, stop active support — no more patches — and eventually, only once adoption data shows the dependent count near zero, physically remove or hard-block it). Throughout, track real usage data (who's still calling it) rather than assuming compliance, and have an exception process for teams with a genuine blocker so the sunset date doesn't become an empty threat that gets waived for everyone at the last minute. The key discipline is treating deprecation as a tracked, funded migration project with an owner, not a one-time announcement.

go deeper

for a junior

Understands deprecation means 'stop using the old thing eventually' but hasn't thought through phased support, patching obligations, or tracking.

for a middle

Can lay out the announce-migrate-sunset phases and knows migration needs tooling/guides, but may not have run usage telemetry or an exception process themselves.

for a senior

Has actually run or closely supported a real deprecation across many dependent teams, including building or requesting migration tooling and negotiating exceptions.

for a principal

Sets the org-wide deprecation policy (lead-time guidelines by blast radius, exception governance, patch-support SLAs during the window) and is accountable when a deprecation goes wrong at scale.

## Why deprecation is the expensive part Deprecation is where a tech radar's governance work actually gets expensive, because moving a technology to Hold is a decision made in a meeting, while getting dozens of teams to actually stop depending on it is a multi-month execution problem with real engineering cost spread across other people's roadmaps. A lifecycle with distinct, well-defined phases exists specifically to make that execution problem tractable and to avoid the two bad outcomes: - a chaotic forced cutover that breaks production systems, or - an announcement that never actually gets enforced and the deprecated library quietly lives forever. ## The four phases 1. **Phase one, announce:** the decision — what's being deprecated, why (the replacement's specific advantages, or a genuine problem with the old library such as unpatched security debt or an unmaintained upstream), what the replacement is, and a target sunset date — gets published somewhere all dependent teams will actually see it, not buried in a wiki page nobody reads. Lead time here should scale with expected migration effort: a config-flag rename might reasonably get four weeks' notice, while a foundational library requiring API rewrites across fifty services might reasonably need six months to a year. Announcing too early, with no clear timeline, trains teams to ignore deprecation notices as noise; announcing with too little lead time turns migration into an emergency nobody had capacity to plan for. 2. **Phase two, deprecate-but-support:** the old library keeps working — critically, it keeps receiving security patches during this window, because forcing a security-vs-deadline trade-off onto every dependent team is exactly the kind of pressure that produces workarounds and shadow forks — while visibly signaling it's on its way out: a compiler or linter deprecation warning, a banner in generated documentation, a note in the library's own changelog. This is the phase where **dual-running** is expected and healthy; the point isn't instant cutover, it's making the coming change impossible to miss while giving teams a working system to migrate from at their own (bounded) pace. 3. **Phase three, migrate:** this is the phase most deprecation efforts under-invest in. A migration guide alone puts the entire burden on each of dozens of teams to independently figure out the mechanical transformation, which is both wasteful (the same problem gets solved fifty times) and slow. Where the change is mechanical enough, automated **codemods** (scripted refactoring tools) dramatically lower the real cost of migrating and should be treated as a first-class deliverable of the deprecation, not a nice-to-have. Equally important is visibility: someone should maintain a tracked, living list of remaining consumers — derived from actual usage telemetry or dependency-graph analysis, not self-reported status — so the organization can see migration progress as a number, not a vague sense that 'most people have probably moved.' 4. **Phase four, sunset:** only after the deadline passes and usage data shows the dependent count is genuinely near zero does active support stop (no further patches) and, eventually, does the library get physically removed or hard-blocked (e.g., pulled from the internal artifact repository, or a CI gate starts failing any build still referencing it). The critical discipline here is that the sunset date has to be real — if it's quietly extended for every team that didn't get around to migrating, the entire lifecycle loses credibility and every future deprecation gets ignored on the assumption the deadline is soft. The way to keep the date real without being reckless is a narrow, explicit exception process: a team with a genuine blocker (a vendor dependency that hasn't caught up, a system in a compliance freeze) gets a documented, time-bound extension with a named owner and a new date, not a silent, indefinite pass. ## Trade-offs - **A long, gentle lifecycle** costs calendar time and requires the organization to run two versions of the same capability in parallel for months, which has real maintenance cost. - **A short, aggressive lifecycle** reduces that dual-running cost but sharply increases the risk of breaking dependent teams who couldn't reprioritize in time, and tends to produce exactly the exception-request pileup that erodes deadline credibility. The right point on that spectrum scales with blast radius: a low-usage internal utility can sunset in weeks; a foundational library touching every service in the company needs a much longer runway and real migration tooling investment. ## Three ways it goes wrong **Failure modes in production:** - **An announcement with no funded migration effort behind it** — the most common. The deadline arrives, most teams haven't moved because nobody gave them time or tooling, and the org either breaks production or grants a blanket extension that becomes the new indefinite status quo. - **Deprecating without maintaining security patches during the support window** — a second. It forces teams into an unsafe choice. - **Having no usage telemetry** — a third. The team running the deprecation genuinely doesn't know who's still depending on it until the hard cutover breaks them. ## How this played out at internet scale A concrete instance: this is close to the shape of Python 2's end-of-life process — a long-announced sunset date (originally 2015, extended once to January 2020), years of dual-running support, extensive migration tooling (the 2to3 codemod and later compatibility shims like six), and, even after the formal EOL date passed, major distributions and package indexes maintained visible warnings for years afterward precisely because instant hard removal at internet scale would have broken far too much running software.

  • Why should a deprecated library keep receiving security patches during the migration window instead of being frozen immediately?
    Freezing patches immediately forces every dependent team into an unsafe trade-off between shipping on a known-vulnerable dependency and dropping everything to migrate on an emergency timeline. Continuing critical patches during the support window removes that pressure and keeps the migration timeline driven by planning rather than incident response.
  • How do you know when it's actually safe to move from the support phase into the sunset/removal phase?
    Real usage telemetry or dependency-graph analysis showing the number of active consumers is near zero — not a self-reported survey or an assumption based on how long the deadline notice has been up — because self-reported migration status reliably overstates actual completion.
  • How should exceptions to the sunset date be handled without undermining the deadline for everyone else?
    Through a narrow, documented process requiring a specific justification (a genuine external blocker, not just deprioritization), a named accountable owner, and a new firm date — kept visibly rare and time-bound, so it functions as a real exception rather than becoming the default outcome that trains every team to ignore future deadlines.

Like decommissioning a building: you announce the closure date early, keep the utilities running while tenants pack, provide movers and a moving guide rather than just a memo, track who's actually moved out room by room, and only then cut the power — with a documented process for the one tenant with a genuine reason they can't move out on time.

saying these in an interview costs you the question

  • Treats deprecation as a single announcement with no funded migration phase
  • Suggests freezing security patches on the old library the moment deprecation is announced
  • Has no way to know how many teams are actually still using the deprecated technology before cutting it off
  • Would grant an unlimited, silent extension to any team that asks
  • Sets the sunset deadline without adjusting lead time to the actual migration effort involved

context