An internal API has a sunset date, but nobody can name every consumer. Traffic remains after the deadline, exceptions have no owner, and the old service still requires on-call support. That is migration debt.
Use one ledger
consumer,monthly_calls,owner,migration_hours,exception_until,last_seen
billing-ui,120000,team-a,24,,2026-07-18
legacy-export,80,team-b,40,2026-08-15,2026-07-17
unknown,9300,,unknown,,2026-07-18
Track three costs separately:
migration_cost = estimated_hours * loaded_hourly_rate
run_cost = infrastructure + on_call + security maintenance
delay_cost = run_cost_per_month + risk_reserve
Illustrative numbers are not ROI evidence. Run downside, expected, and upside scenarios, especially for unknown traffic and estimates that exceed one sprint.
| Gate | Required owner | Stop condition |
|---|---|---|
| consumer inventory | platform | unknown traffic above threshold |
| migration kit | API team | clean-room example fails |
| exception | business owner | missing expiry or rationale |
| shutdown | incident owner | rollback untested |
Make exceptions expire automatically. An expired exception should page its owner or disable the waiver workflow—not silently become permanent. Keep read-only telemetry after migration long enough to detect late consumers, but define retention.
This ledger does not capture every organizational dependency or prove that shutdown is cheaper. It makes assumptions reviewable. Which is more expensive in your system: one month of old-API operation or one unknown high-value consumer outage?
Top comments (0)