Deprecating an internal API
Killing a piece of internal surface area — when, how loud, and what the deadline actually means.
When to reach for this
The shape of the problem this playbook is for.
- A platform team has two ways to do the same thing and is paying maintenance on both.
- A new pattern has emerged that everyone agrees is better, but old callers haven't moved.
- An engineer has filed the seventh ticket asking 'which one should I use?'
Signals you're ready
If these aren't true, you're not deciding yet — you're scoping.
- You can name the replacement and link to its docs.
- You have telemetry on who's still calling the old thing.
- There are fewer than 50 callers (and you can list them).
The rubric
Numbered, weighted, opinionated. Walk through them in order — the first decisive answer often ends the meeting.
- Decisive
Is the replacement actually better for the caller, or just better for us?
Better for the caller (clearer, faster, fewer footguns) → migration is a favor. Better only for the platform team → expect to do the migration yourself, not just announce it.
- Heavy
Do we have telemetry that can tell us when the last caller moves?
If yes, you can run the deprecation by data. If no, instrument first — you cannot deprecate what you cannot measure, and the 'last 5%' will eat the schedule.
- Heavy
Who owns the migration of each caller — us, or them?
<10 callers: do the migration yourself, send the PRs. 10–50: write a codemod, do the long-tail yourself. >50 or external callers: announce, hold office hours, accept it'll take 2× longer.
- Tiebreaker
What's the deadline, and what happens at the deadline?
A deadline without a consequence is a wish. Pick a real consequence (returns 410, throws at import, fails CI) and announce it from day one. Pad by 30% but don't move it once announced.
Default pick
When the meeting is going in circles, ship this — and write down what would change your mind.
Red flags
Patterns that mean the playbook isn't your real problem.
- The deprecation has been 'in progress' for more than two quarters with no measurable drop in callers.
- The replacement requires more code at the call site than the thing being deprecated.
- The deprecation announcement is in a Slack channel nobody pinned and nobody mutes either.
Real applications
The playbook used in anger — context and outcome.
- ContextTwo RPC libraries doing the same thing; new one launched 18 months ago.OutcomeCodemod migrated 80% of callers in one week. Long-tail (12 services) took six weeks. Hit the cut date by setting CI to fail on import of the old one two weeks early.
- ContextPublic webhook v1 → v2.OutcomeExternally-visible deprecation. 6-month overlap, monthly nudges, 90-day final warning. 4% of partners needed manual reach-out; cut anyway.