When the constraint moves, reprice the code
Technical debt is extra future cost accepted for a present capability. When the constraint moves, sunk cost keeps the code alive past its expiry
When the constraint moves, reprice the code from zero.
The harder code was to build, the easier it is to mistake past effort for present value. Sunk cost drives the mistake. Technical debt makes it harder to see, because carrying the debt was once rational: the benefit disappears while the maintenance survives, but the old decision still sounds like a defense of the code.
While the constraint holds, the workaround is debt worth carrying
Pressure code is code built around a constraint: a tool that almost fits, an ecosystem still settling, a deadline with no slack. It mirrors the constraint's shape. Pinned builds, special-case handling, patches that exist only because the thing underneath won't do what's needed yet.
Calling it technical debt is exact, and the definition matters: extra future cost accepted to get a present capability. The patches buy a running workload now by creating maintenance a mature platform would avoid. Carrying that trade is a rational investment for exactly as long as both sides of it exist.
The constraint can be moved on purpose
A platform too immature to run a workload cleanly forces the trade in its sharpest form. Making it work means a pinned build of the framework underneath and a compatibility patch for each edge the platform hasn't sanded, and the result still fails loading two gigabytes into 96 GB of addressable VRAM. Two weeks of that is a defensible price while switching platforms costs more than carrying the workaround, because a workload that mostly runs beats one that doesn't run at all.
The constraint doesn't have to move by itself. Moving the workload to a platform with a mature toolchain kills the constraint deliberately, and the same service runs there unmodified. No patches, no memory bug. Every patch is worth nothing in that moment, because the only thing any of them ever did was stand in for a gap that no longer exists. Nothing about the code changed. Only the constraint under it did, and all of the code's value went with it.
The benefit can expire while the debt remains
The capability side of the trade ends and the maintenance side doesn't. Expired code is the honest name for what's left. Debt has a present capability to point at. Expired code has only the story of what it cost, and that story does all the arguing: the weeks it took, the fight it survived. A workaround that took an afternoon gets deleted the day it stops earning. One that took two weeks survives review after review, and the difference between them is nothing the code does.
Dependents prove use and entanglement at once
Dependents don't settle the valuation either. They prove use and entanglement at the same time, and their count can't separate the value the code still creates from the cost of replacing it. More dependents raise the switching cost and widen the blast radius whether the code is earning its place or holding the shape of a problem that no longer exists. Infrastructure with a hundred dependents can hide severe debt in its implementation, and a workaround with none can be the most rational investment in the system. The count affects the decision. It cannot settle it.
The test is whether you'd build it again
Almost any code disappears if the requirement behind it is deleted, so the counterfactual has to be sharper than asking whether anything would miss it. Two questions do the repricing. What current constraint still requires this code? And if the same problem arrived today, would this get built again?
A protocol that still has to be spoken answers the first question for as long as the obligation holds. The implementation may fail the second and still need replacement, but it hasn't expired.
Code that fails both questions has, and everything spent on it is a receipt, not a reason.