Technical Debt: Recognising the rate of interest

So, I’ve had this idea to break up technical debt into two high-level categories — high interest and low interest. Somebody may have already expanded the concept to this level of detail, but I came up with this on my own, thus it doesn’t count as plagiarism :-D

A quick recap of technical debt

Technical debt was a term coined by technical people as a metaphor for helping to explain the accumulation of complexity in software systems that causes a slowdown in ongoing development — a time penalty on adding new features. Technical and non-technical people alike are familiar with financial debt and its impacts, and recycling the word ‘debt’ in a technical context appears to make for a semantically viable metaphor for all to comprehend.

DDD can’t help with predicting the future, only with understanding what’s known in the present

One of the inherent challenges in building software is that we don’t know what we don’t know about the domain we’re working in. As much as engineers love to believe in infinitely extendable designs, the reality is that you’re deluding yourself when believing that your designs/models can effortlessly accommodate future changes in business context and product direction. The fictitious universe where significant new features can be indefinitely accommodated at will, without any refactoring of existing code, is a universe reserved for those who like to talk a big game, but who’ve never actually built a real-world system. The delusion leads us blindly towards creating ugly, generic abstractions that manifest themselves in code that appears foreign to the problem its trying to solve.

We must acknowledge that one of the inherent challenges in building software is that we don’t know what we don’t know about the domain we’re working in.

We must appreciate, though, that we do create a lot of conscious technical debt when we build systems. And that’s perfectly okay — it’s all part of the trade offs we make every day between evolving a product quickly in the short-term vs looking after long-term sustainability. Nobody (well, not me) is saying that all technical debt is bad, far from it. Just like in the financial world, there are many cases where taking on debt is a strategic win, where the advantages of accumulating the debt in the short-term outweigh the long-term disadvantages.

Introducing the ‘rate of interest’

The issue as I see it is that I’ve not come across a succinct way to categorise the technical debt we consciously create, such that we can distinguish between debt that is ok to accumulate versus debt that is far more damaging to accumulate. Without this formalised approach to categorisation, it makes it harder to be strict on ourselves when making our conscious trade offs. Ideally we need a method of categorisation that also works for non-technical folk, thus preserving the value of the overall debt metaphor.

the interest burden becomes so great that the borrower is capable only of meeting the interest payments

Let’s consider that a piece of arbitrary technical debt adds an overhead of 10% on all new feature development. If we pay back half of the debt, that brings down the overhead to 5%, and we keep paying it back until we remove the overhead altogether. Now let’s consider that the difficulty in paying back the debt is measured in terms of its interest rate — i.e. the harder it will be to refactor our system to remove the debt, the higher the interest rate assigned to it.

The fine art of technical solvency

If we find ourselves burdened by an excess of high interest technical debt, we’ll end up like the financial borrower trapped in a debt spiral, only able to afford the interest payments, never able to pay back the underlying loan. In such cases, the rate of accumulation of high interest debt can grow exponentially — high interest debt has a tendency to drag you down a path towards even more high interest debt. And the interest rates on existing debt somehow keep on rising.

the rate of accumulation of high interest debt can grow exponentially

At some point you reach the point where the line between solvency and bankruptcy becomes almost imperceptible. There are a whole number of potential indicators of when you’re crossing the line into technical bankruptcy — here are just some examples:

  • “Simple” things that were meant to take days, somehow take weeks or months (or years!)
  • Your teammates never seem to make it to stand up on time. And if they do make it at all, they’ll probably be sitting down.
  • Your P3 bug backlog is so full, and growing daily, that nobody even cares about it any more.
  • Nobody ever bothers to challenge decisions they don’t agree with
  • When a test suite is failing, everyone just blames it on Jenkins instability.
  • Somebody turned off the static code analyser to get it to shut the hell up. The rules were too strict, right?
  • All anyone seems to do is moan. All bloody day.
  • Your company network appears to be issuing a denial of service attack on Facebook

If we do our best to limit ourselves to low interest technical debt, then we give ourselves a better chance of being able to afford to pay back the underlying loan

Higher or lower?

One of my favourite insights from Martin Fowler is his view that software architecture constitutes those decisions that are both important and hard to change. This was taken from a keynote at OSCON in 2015. If we assume this to be true (and it is because Martin Fowler said it), then it follows that we can reasonably define high interest debt as relating to the architectural aspects of software. For me, this is an extra incentive to take Eric Evans very seriously when he advises that we break up our domain into distinct Bounded Contexts.

we can reasonably define high interest debt as relating to the architectural aspects of software

In my experience, so much high interest (architectural) debt is rooted in failing to acknowledge the natural boundaries that exist within a complex domain. With this in mind, I will always make a point of explicitly modeling these boundaries — at least as far as they’ve been discovered in the present moment — from an early stage in any software product/project.

But, what about startups?

I’m not for one moment suggesting that a startup loses focus by carving their fledgling software into a whole bunch of fully distributed bounded contexts, manifested as autonomous microservices. The operational overhead will most likely turn into a very painful — and potentially fatal — distraction. Trying to scale a business too early is a bad idea. However, once you’ve arrived at something resembling product-market fit, I don’t believe it’s wise to be thoroughly complacent with architecture/design.

before you’ve established some form of product-market fit, it doesn’t really matter what the hell you do

Ultimately, a microservices architecture will succeed as a side effect of having identified the right domain boundaries. Conversely, it will likely fail if the boundaries are wrong — the dreaded distributed big ball of mud! Thus, we should recognise that the real value lies in establishing the domain boundaries early within a modular monolith, and delay the operational optimisations until later. We can start splitting up the modular monolith at that point in the future when we begin to ramp up autonomous teams and want to leverage the opportunities of scale. If we’ve managed to keep our technical debt interest low (avoiding the monolithic big ball of mud), then the job of carving up will be many orders of magnitude easier at that point.

a microservices architecture will succeed as a side effect of having identified the right domain boundaries

Summing up

Don’t forget that it’s not always our intention to eradicate all conscious technical debt — it can be a competitive advantage to take it on — but there appears to me plenty of sense in aiming to keep the rates of interest low. Sometimes, it may be the case that adding just a couple of extra days development time up front is enough to significantly bring down the rate of interest in the long-term, albeit not avoid debt altogether.

Software engineering nut. Cyclist. Musician. Dog lover