Instead of thinking of it as "debt payments" you could just think of it as high operating expenses for the development team, and invest in reducing them.
But your alternative mental model is spot on, it's a costly hindrance to development, not a cost imposed by the code itself. And "only until you stop working on that code" is unfortunately just half of the truth, because a team that is used to living with a problematic style instead of dealing with it might easily end up repeating the patterns they abhor when given the chance to greenfield, because they don't know the alternative well enough.
Both "code rot" and "technical debt" are concepts that, unlike their real-world analogs, are only problematic in context of ever changing environment. I feel this is a crucial and unmentioned difference that makes the analogy bad.
All other things being equal, this is true, except for hardware issues where replacement parts may be very expensive or completely nonexistent.
This should be trivial on the small (just pin versions and disable automatic updates of your build tools / package repos), and with recent proliferation of cheap VMs and containers, it should be simple over time - you should be able to pull a 5 years old image full of old software and rebuild the original binary.
> There may well come a point where just getting the damn thing to build so you can release a version with whatever vulnerability patched can cost more than the remaining lifetime value of leaving it running. In that case, it's already dead, it just doesn't know it yet.
Vulnerabilities aren't sins, they are things that can be fine to leave unfixed. The software isn't dead, it'll just keep running with a known exploitable issue.
Yes, and in the not uncommon case where part of the build environment is left unspecified, the untouched code accrues debt over time. As you say, it's possible not to take on that debt by making a significant investment up front. This isn't an argument against the debt metaphor, it's an argument for it.
> Vulnerabilities aren't sins, they are things that can be fine to leave unfixed.
My point doesn't change if you s/vulnerability/sufficiently serious vulnerability/.
It should be taken as a given that code (and everything else) exists in an ever changing environment. Computers are physical machines; they run down over time. Capacitors need to be replaced, and you've got to blow the dust out of your fans once in a while.
Especially in web development, the environment changes quickly. Who could have foreseen that the authors of the JavaScript spec would introduce their own "remove" function? Not me: I left my code unchanged, and it broke. Or, more technically, it rotted.
Maybe I should've put it in a different way: one of the biggest benefits of putting things in a digital form is that the digital form is immune to decay, as long as someone maintains the infrastructure for copying and reading that digital data. The default state of digital data - including code - is not rotting. We do a lot of extra work to make it rot. So the question should be, why are we doing it, and shouldn't we embrace this feature of permanence that we get for free? It's not impossible [0][1].
Version pinning and only doing updates in explicit, planned steps, is a start. Runtime environment can be virtualized and thus made to outlive hardware (virtualization is a way to turn hardware into software, to make the former immune to decay). Web folks have Babel, which today is used to evolve the language faster than the browsers can keep up with, but it could be used for the reverse - instead of compiling ES1234 into ES5, it could also be made to compile ES5 into whatever backwards-incompatible ES-whatever the browsers will be running 5 years from now. This is how you restore the pristine state of code undecaying. The nice thing about the digital medium is that it only requires maintenance at the boundaries of change, and we get to move those boundaries - we could opt to keep them concentrated in few places (like virtualization software, transpilers, hardware abstraction layers), instead of spreading them out everywhere and then saying that the code "rots".
--
[0] - Common Lisp has many warts that make it suboptimal for modern software development, but one of the best things about it is that CL code doesn't rot much. When you pull in a CL library that's 15-20 years old, you expect it to run without changes. With 25+ years codebase, you might need some fixes, mostly because the language wasn't standardized until 1994.
[1] - Maintaining backwards compatibility matters too. I can take a Windows .exe compiled 15 years ago and I expect it to run on a modern Windows machine just fine. Arguably, this is one of the main reason for success of Windows - Microsoft put in work to ensure old software doesn't break in new Windows versions.
I agree the users of these stacks are often short sighted and you could call that bad engineering. However it's very much a feature of those platforms, not so much individuals decisions on then.
Personally I prefer ecosystems with large common libraries that are highly stable and cohesive to avoid those problems .. but the reality is so much software is built in fragile/high maintenance stacks these days, npm and react being the worst bit not only examples of extreme code rot from time decay of the ecosystem. Try updating a react app from two years ago to really understand..
Perfect example: I'm in SV, and I bet there's a not insignificant slice of the population around me who think that the cure to budget deficits (i.e., debt) is to reduce income by cutting taxes, based on a mystical belief never seen in reality that the growth fueled by the tax cuts will result in both lower taxes for the population and higher tax revenues for the government (i.e., investment).
I'm almost 50 years old, and there has never been one iota of truth to this notion in my lifetime. Not one teeny tiny iota. But some people just can't resist going back to that well over and over again with the same results every time. The notion that you can kill two birds with one stone, and both ignore debt and create wealth at the same time via magic Austrian fairy dust must be very powerful. It's like a black hole of self-evident idiocy that people keep flying into for some reason. It must be a form of cognitive bias, but if so I don't know what to call it.