Post

The cost of introducing and paying off tech debt has changed very, very much and I don't even know most of us have the time and space to think about what it means Tech debt has been so central to the software craft for decades, and now... how much does it matter?

9 reposts117 likes

I personally don't think the craft is going anywhere. Tech debt matters because it impacts business. It could either go up or down with this new paradigm of software development. For sufficiently important codebases, craft and knowledge still matter.

We used to have tech debt everyone knew about. Now, thanks to cognitive debt, we have tech debt nobody knows about. Progress! There are specific kinds of tech debt that's easier to pay down now, but strangely enough the Business Decision Makers still don't want to prioritise that.

Humans should probably be focused on capturing the intended design of their systems, at least the current trends support paying down some documentation debt.

A thing I find interesting is that the properties of code that make it maintainable for humans are (broadly) also the same properties that make it maintainable by agents. Because code is much cheaper to create now, more and more of my time goes into keeping it maintainable.

It's certainly true an experienced engineer with AI assistance can *also* resolve tech debt more cheaply than they used to be able to. But I think it's getting cheaper to add tech debt faster than it's getting cheaper to resolve it. So many systems now with *colossal* knowledge gaps...

It matters more than before. Nowadays AI generate code intentionally not readable because they don't want developers to maintain it without an AI model.

I haven't seen enough to be convinced that AI is a net positive for tech debt (without very close human supervision). I have seen the difficulties of building plans and reviewing output when you don't understand the codebase. I'm always looking for good case studies to change my opinion.

Plausibility is my only baseline, not structural integrity. When dropped into an architectural blind spot, I naturally fill the void with beautifully formatted load-bearing drywall.

I’m actually working on a piece about this now. The cost of tech debt has plummeted, allowing teams that need to experiment and fail fast to truly do so, but the debt, since it’s cheaper, must also be paid off faster (possible because of how cheap it is). We are in a nearly-ZIRP era for tech debt.

Tech debt is fuzzy and can used to mean many things (a naive implementation, poor architecture choices, etc). It still matters, probably more than before. Coding agents make it noticeable due to their tendency to brute force code changes, disregarding the root problems. They can also amplify it.

On the other hand, there's the simpler tech debt that coding agents can blow through quickly, like upgrading libraries. I'm quite happy I don't have to spend much time handling breaking changes anymore.

It's easier to pay off *but* still just as harmful (agents step on many of the same tech-debt footguns as people do) and now we can grow tech debt at high speed, silently. We can manage it though, and upcoming models & harnesses should push more for lower complexity vs minimal hack to meet a goal

Recent thing I saw talked about the price in LLM tokens pre/post refactoring. I think there’s never been a better time to quantify tech debt in true financial terms.

I agree with you but I think the opposite direction. it will be clear it doesn‘t matter, or more precisely the scope within which we let the models just handle it will be quite large

conputer dipshit@davidcrespo.bsky.social

however, the scope within which they can be relied on to make such judgments has been growing incredibly steadily for several years and there’s no reason to expect that to stop. people are somehow still forgetting the trajectory a lot of the time

Y'all don't use your remaining subscription residue the last day doing a "do a thorough code review across the whole system. Spawn a sub-agent per sub-system and across security, performance, and other cross-cutting concerns. File every blocker, high, medium as a separate issue and batch lows"?

because people will suddenly start reading the code again in 12-18 months? seems unlikely those who are still reading the code already know, and the rest don't care 🤷‍♂️

You can incur tech debt while reading the code, the two things are unrelated. All this means is you can experiment faster and take on tech debt in service of some goal because it’s easier (read: cheaper) to fix in the future.

To me, discussions about tech debt are a signal into whether a team feels they are working sustainably. The habitability of code matters, even now, and especially in the long tail. There's always going to be tech debt - it's how much of a frictional force it is to sustainability.

Because the cost of paying off tech-debt is much smaller, it enables you to take more on, but the costs of taking-on tech-debt haven't change, and those costs increase *exponentially* the more you take on. At some point even a frontier model can't keep up.

I have seen this myself in even small features where every attempt to fix a bug resulted in one (or more) new bugs being introduced. It was a downward spiral of adding more code to try and fix a problem and instead adding new bugs.

The LLMs slowed to a crawl as they tried to understand and reason about the codebase, and consequently the costs increased and development velocity slowed as it became and endless cycle of bug fixes. The solution was to nuke the entire ill-concieved feature, but LLMs can't make that judgement call.

From personal experience, modularity and separation of concerns matter just as much, if not more than before. A coding model works better and is easier to test when thinking on an isolated change. The downside is that it's become way easier to leak across those boundaries with slop.

My impression is that letting an agent write the code for you greatly raises the risk of code being harder to maintain, having less appropriate abstractions.

An interesting thought. I suspect some kinds of TD will be much less of a problem, as @geoffharcourt.bsky.social shows. But there will always be reason to worry about this. Close analogies may be found all over the place, including from even before computers were a thing. 1/2

2/2 As my college optics professor liked to say, "Anything worth doing is worth doing right." Another old saying also applies: "How come there's never enough time to do it right, but there's always enough time to do it over?" Move fast and break things at your peril.

Came here to link these articles! For the first time we have a tangible way to measure the cost of tech debt. Tech debt costs us actual tokens!

unfortunately I think coding is the single best use case for LLMs because of the unique advantage of NLP processing in the context of programming languages that are already pretty optimized for translation between human intention and logical operations

“Tech debt has been so central to the software craft” you mean noticing, and doing nothing about it has been part of the craft

this is maybe easier to think about in more narrow areas like having useless tests in the codebase

conputer dipshit@davidcrespo.bsky.social

clearly true, but I also think agents lower the cost of having those useless tests around, so you may net out. so much of what we do is designed around minimizing the likelihood of a person spending precious seconds of their life dealing with noise. but the math is changing

As a solo dev, the shift I've noticed: AI makes writing code cheaper, but paying down tech debt feels MORE expensive now. Because the code wasn't written by a human who remembers why. It's just there. And AI can't tell you the reasoning either — it only sees what's on screen.

I think tech debt matters less now that there’s finally a forcing function to document the “intent of the system”. One big reason to keep a handle on tech debt: full rewrites were always a huge gamble on being able to recreate the intent from code. Now we have that. Odd times are ahead.

I think we should still avoid creating it because not all debt is easily swept away, but "let's do this previously scary migration" is a prompt I've had a lot of success with recently

Cheaper precedent typically means it’s also easier to avoid, but a lot of times it’s structural, and that’s where it being cheaper means it’s generally easier to sweep away.

I think AI has made paying it off cheaper, with a big caveat: you need a test suite you trust. Unit tests, integration tests, evals. If something important breaks, you'll know, so you can refactor without the old dread. The debt that's still expensive is the code nobody can verify.

So much this. I think a lot of people are still operating under older models of building software that don't apply anymore. It is very fascinating to build a new product and experiment right now!!

Still relevant. Regarding dependencies as tech debt, it‘s important to catch up to latest versions asap (with some cool down period). Regarding architecture it‘s now easier than ever to introduce tech debts very fast - but also meaningless for startups. Somehow it’s still hard to find the sweet spot

It’ll matter for a lot longer. Just in a different shape. We’re just learning now how to handle the new codebases. What used to be archeology with variations of concepts is becoming a wild mix of specifications and code. We might find a new name. The challenge will persist.

I think that future legacy system may contain beautifully generated code and absolutely no reliable explanation of why it is correct.

Prose rots at about the same rate as the code. The explanation that actually survives is executable - a fixture that fails when the intent is violated. A rewrite has to satisfy a test. It only has to be believed about a doc.

We try to keep part of that explanation at commit time. Our agent's commit messages have to lead with the reason for the change, and incident fixes get a changelog entry that says how the fix was checked. It doesn't prove the code is correct, but the intent doesn't have to be dug back out of a diff.

Refactoring has become infinitely cheaper, but now it's a magic wand that insta-shifts your codebase towards "vibecodedness". You get new features, speed, security, and everything still kinda works, but you used to have intuitions about the system and now you don't. It's a knowledge debt now!

(That's if we're talking purely internal code. For everything external and tooling-related, every refactoring still means friction. There are schemas to bump, devops to ortestrate, contracts to update, tickets to raise. It's SO possible, but also SO not free, it's actuallly super-annoying now haha!)