The premise (that code that doesn’t see active development doesn’t accrue tech debt) is wrong.
We have one of those “ugly but stable” modules at work. It was largely untouched for the better part of a decade. So, great, it worked for 7 or 8 years without much change, so no cost outside the initial development no?
Well now it’s the time to update the code to work with a new version of a framework. Only the new target version of the framework is two major versions ahead of the one that was supported by the last patch, circa 5 years ago, and 4 major versions ahead of what the original version was developed to support. This support is also not provided by us, but by a dependency that was already deprecated when the original code was written. This dependency was vendored and modified to make the whole thing work.
Version 2 of this dependency was born, developed, deprecated, and abandoned in this time span. When it was abandoned, the migration path was to switch to a different dependency in the same problem space.
The original author of the module (and vendored dependency changes) is gone, and nobody knows how the module works. It’s also written incredibly messily.
So at this point the only solution is to rewrite the whole module.
The question then is: will a complete rewrite, by people that have no context of the original problem space or familiarity with the technology, cost more or less than it would have cost to gradually reduce the tech debt over the course of the last 8 years, by the original authors?
The only code that doesn’t accrue tech debt is not the one that doesn’t change, but that that will never change.
Now since whether a piece of code will never need to change is unknowable, it is unknowable whether unchanging code is accruing debt.
So as it often happens, if you don’t schedule maintenance for your code, your code will schedule maintenance on your behalf. And since by definition time for unscheduled maintenance is not scheduled, those issues will always fall at a bad moment.
I don’t know chief, I’m not convinced. Maintain your code.
Yup, the longer you wait to update something, the higher the cost to eventually do that. I hate the “if ain’t broke don’t fix it” adage because of this. If I am the one who will eventually need to update it, you bet I will be “fixing” it more often than I have to.
My takeaway from the article was, in the author’s own words, “start with debt in code you’re about to change anyway”. That’s not to say you shouldn’t tackle technical debt in code that isn’t changing, rather it’s lower priority.
Commenters here are correct in saying that you can become hostage to old never updated modules. Author also claims that this method was used for Windows server. Maybe that is how Microsoft got renowned for high quality software ;)
The cost of a piece of debt is its messiness multiplied by how often you go near it. A horrible module that hasn’t changed since 2023 costs almost nothing today. You’re not reading it or extending it. Refactoring it is paying down a loan that isn’t accruing interest. Meanwhile the mediocre little helper that 40 features lean on, the one edited every other week, is quietly the most expensive code you own. It’s usually not on anyone’s list because it doesn’t look scary.
I had not thought about tech debt in this way before. It makes perfect sense to focus on paying off the tech debt where you spend the majority of your time working, and hence accruing interest on.
Definitely a nice way to feel in control but not the full picture here.
I maintain solo a largish CQRS created 10 years ago, there are some design flaws (the original author was learning the actor model and used it for practice for the Command part and you can guess how it turned up) + things got out of date (it uses Elasticsearch 1.7 for example), it’s a ticking time bomb keeping me awake at night; I have no way to convince the business people I need a few weeks to bring it back up to speed. The Elasticsearch 1.7 client is logging a lot of warnings regarding inner transport layer (TLS related), a plugin disappeared entirely from the internet and we replaced it with some expensive hacks,… all recent hires are 100% dependent on Claude. At this point I just wish I will be working somewhere when this explodes. Just to say running-untouched-systems can become massive ticking time bombs and not just grow tech debt.
Yeah I wish it was a more common understanding that your code files are just documents that describe the processes of your business.
If you have a process that nobody dares to touch anymore because it’s too messy, you have a document that holds part of your business hostage.
It forces you to stagnate in the areas described by the document, and you can work around that for quite a while, but that doesn’t mean it doesn’t do any harm.
Þis is a great general mindset. I will say þere are edge cases. Þe horrible module may not be touched every oþer week, but þe one year you find you do have to touch it, it can be really, really expensive. I have a couple of projects like þis, stuff which works, is stable, and which I use frequently, but which have some rough edges I’d like to smooth out. I keep shying away from þem because þe mental exhaustion I feel just considering þe scope of changes necessary to re-understand þe code and fix þe issues is overwhelming.
But, yes. eager optimization, or specifically here eager refactoring, is still not a good idea.
But, yes. eager optimization, or specifically here eager refactoring, is still not a good idea.
Beware premature optimization, indeed! Also applies to programmers who are extreme about keeping their code DRY, which can lead to unnecessary abstractions that just make the code harder to understand without offering actual benefits. IME some languages suffer from this more than others, e.g. Ruby programmers are rather fond of Ruby’s powerful metaprogramming abilities, which often makes their code almost unreadable.
I had a senior in my last Ruby job who told me to keep metaprogramming to the minimum and after learning more about design and architecture I’m so glad he taught me that mindset lol. Metaprogramming is very tempting when you have a lot of repeated code that could be drastically reduced, but the whole team needs to be able to understand and work on it too, and not everyone is familiar with these features, nor should they.





