Deprecation program
A deprecation announcement changes nobody's behavior. Teams migrate the week
their code breaks, not the week you ask, so a "deprecated" label with no
telemetry, no tooling, and no off switch becomes a maintenance tax you pay
indefinitely. Run it as a program with a burndown and a real end date, not a
wiki page and good intentions.
Method
- Instrument the surface before you say a word. Add per-caller telemetry:
which team, service, and code path hits it, and at what rate. Tagged access
logs or OpenTelemetry spans beat an aggregate counter, because "2M calls a
day" names nobody to email. You cannot deprecate a caller you cannot
identify.
- Publish a notice carrying a hard date and the replacement. State the
exact date the system stops answering, the migration target, and the reason.
Emit the warning at the call site too: a
Sunset response header (RFC 8594),
a @Deprecated annotation, a startup log line. A notice with no date is a
wish.
- Ship the migration, not just the docs. Write the codemod (jscodeshift,
OpenRewrite, a scripted sed pass), the shim, or the adapter that does the
mechanical rewrite. Every hour of toil left on a caller multiplies by the
caller count; a codemod serving three teams has already paid for itself.
- Close the front door the day you announce. Block new adopters at once: a
lint rule, a denied build dependency, a registration flag that refuses fresh
integrations. A "deprecated" system still gaining callers is not being
deprecated, and the newcomers shout loudest when the date lands.
- Burn the list down with comms tied to the telemetry. Track remaining
callers as a countdown and mail the specific teams on it at 90, 30, and 7
days, not a broadcast channel nobody reads. When a team stalls, escalate to
its manager with the exact call counts your instrumentation produced.
- Rehearse the shutoff with a reversible brownout. Before the real date,
fail all calls for a scheduled hour, then restore. Stragglers feel the break
while you can still undo it, and hidden dependencies surface before they
become an outage. Keep a logged, expiring break-glass path for true
emergencies.
- Delete the code and tombstone the address. Remove the implementation and
leave a clear error at the old entry point pointing at the replacement. Code
kept "just in case" gets re-adopted and quietly un-deprecates itself, so
close the program by making the old path impossible to return to.
Checks
- Can you name every team calling the system this week from telemetry, rather
than guessing from memory?
- Does the notice carry a specific off date and a migration path a caller can
complete without opening a ticket to you?
- Is a brand-new caller blocked from integrating today, or can the list still
grow under you?
- Did a timed brownout rehearse the shutdown before the real one fired?
Boundaries
This covers retiring a system you own that has external callers. A purely
internal refactor with no downstream consumers needs none of the ceremony. A
security kill switch that must fire now overrides the comms calendar: run your
incident process, not a 90-day burndown. Match the notice window to your
organization's API deprecation policy and any contractual commitments to
customers.
1---2name: deprecation-program3description: Run a deprecation from usage telemetry through a hard sunset date, with migration tooling and staged comms, so a system retires without stranding its callers. Use when you own an API, endpoint, library, or service that must be turned off while other teams still depend on it.4---56# Deprecation program78A deprecation announcement changes nobody's behavior. Teams migrate the week9their code breaks, not the week you ask, so a "deprecated" label with no10telemetry, no tooling, and no off switch becomes a maintenance tax you pay11indefinitely. Run it as a program with a burndown and a real end date, not a12wiki page and good intentions.1314## Method15161. **Instrument the surface before you say a word.** Add per-caller telemetry:17 which team, service, and code path hits it, and at what rate. Tagged access18 logs or OpenTelemetry spans beat an aggregate counter, because "2M calls a19 day" names nobody to email. You cannot deprecate a caller you cannot20 identify.212. **Publish a notice carrying a hard date and the replacement.** State the22 exact date the system stops answering, the migration target, and the reason.23 Emit the warning at the call site too: a `Sunset` response header (RFC 8594),24 a `@Deprecated` annotation, a startup log line. A notice with no date is a25 wish.263. **Ship the migration, not just the docs.** Write the codemod (jscodeshift,27 OpenRewrite, a scripted sed pass), the shim, or the adapter that does the28 mechanical rewrite. Every hour of toil left on a caller multiplies by the29 caller count; a codemod serving three teams has already paid for itself.304. **Close the front door the day you announce.** Block new adopters at once: a31 lint rule, a denied build dependency, a registration flag that refuses fresh32 integrations. A "deprecated" system still gaining callers is not being33 deprecated, and the newcomers shout loudest when the date lands.345. **Burn the list down with comms tied to the telemetry.** Track remaining35 callers as a countdown and mail the specific teams on it at 90, 30, and 736 days, not a broadcast channel nobody reads. When a team stalls, escalate to37 its manager with the exact call counts your instrumentation produced.386. **Rehearse the shutoff with a reversible brownout.** Before the real date,39 fail all calls for a scheduled hour, then restore. Stragglers feel the break40 while you can still undo it, and hidden dependencies surface before they41 become an outage. Keep a logged, expiring break-glass path for true42 emergencies.437. **Delete the code and tombstone the address.** Remove the implementation and44 leave a clear error at the old entry point pointing at the replacement. Code45 kept "just in case" gets re-adopted and quietly un-deprecates itself, so46 close the program by making the old path impossible to return to.4748## Checks4950- Can you name every team calling the system this week from telemetry, rather51 than guessing from memory?52- Does the notice carry a specific off date and a migration path a caller can53 complete without opening a ticket to you?54- Is a brand-new caller blocked from integrating today, or can the list still55 grow under you?56- Did a timed brownout rehearse the shutdown before the real one fired?5758## Boundaries5960This covers retiring a system you own that has external callers. A purely61internal refactor with no downstream consumers needs none of the ceremony. A62security kill switch that must fire now overrides the comms calendar: run your63incident process, not a 90-day burndown. Match the notice window to your64organization's API deprecation policy and any contractual commitments to65customers.