This is a topic which almost all non-technical and a lot of technical people don’t understand. This is sad and somewhat ironic because, if you are in any way involved in the software development business, you HAVE to understand it.
I think part of the problem is that, to non-technical people, Tech Debt sounds very nebulous and like precisely the kind of excuse that software engineers come up with for not getting stuff done.
Be assured that tech debt is very real and very deadly. Even those people who do understand what it is find it all too easy to kick the can down the road. Never forget the old saw “a stitch in time saves nine”.
So What is It?
Firstly, let’s explain the analogy: it’s called “debt” in part because you pay “interest” on it. That interest consists of the extra time and risk (therefore, cost) of adding or changing product features.
Furthermore, just like a credit card, the interest compounds. If you don’t address the current debt but go ahead and build new features anyway (i.e. spend more) then you are building those new features on top of your existing debt, meaning you’re paying interest on interest.
The only way to avoid paying interest is to pay back the debt. If you let the debt grow too far, you’ll end up spending more servicing the debt than building new features. Ultimately, you’ll become bankrupt.
Just like other kinds of debt, it’s all too easy and tempting to ignore but it never goes away if you do that – it just gets worse.
Err…So What is It?
Let’s try another analogy: think of your product like a building. Each feature you build is a floor you add to the top of your building. In order for a new floor to stay up, it’s dependent on the support of all the other floors below.
Imagine your building has 8 floors. Now you’ve got demand from new tenants so you want to add a 9th floor. Easy right?
The problem is that the 8th floor isn’t in great shape. It looks ok from the outside but remember you put a lot of pressure on Mikey, the contractor who built the 8th floor, to get the job done because you had tenants waiting? Mikey’s a good guy but he definitely cut some corners to make the deadline you imposed. That wall that was supposed to be load-bearing is just a facade. The wiring is not up to code. The plumbing was rushed so it’s leaking – you haven’t seen the stains on the ceiling of the floor below yet…but you will.
And…remember when you built the 7th floor? That contractor, Dave, didn’t really know what he was doing, did he? He didn’t understand architectural diagrams properly and didn’t know where the load-bearing walls were on the lower floors so he didn’t really lay out the 7th floor properly.
Oh…and don’t forget that Brian who built the 6th floor wasn’t involved in the building the original 5 floors so he didn’t understand the specialized heating system that had been put in and just added to it using standard components. The heating has never worked quite right on the 6th, 7th and 8th floors, has it?
So, ready to build that 9th floor? You could just go ahead. It’ll probably be ok, right? I mean, the building hasn’t fallen down yet…
I think you get the point.
Of course, when it comes to buildings, this is unlikely to happen, at least in a modern, industrialized country. We have professional architects, permits, building codes and inspectors.
Guess what? There ain’t no permitting or inspection agency for software development (outside of some very specialized areas). It’s the Wild West.
The causes of Tech Debt are manifold but I would say these all boil down to three root causes:
- Time pressure. Needing to meet a deadline is just business reality. However, time pressure leads inevitably to corner-cutting. Corner-cutting creates tech debt. Beware artificial ship dates and their hidden cost (more below).
- Pivots. Pivots are also part of business reality, especially for a startup. The only alternative to pivoting is flogging a dead horse…and then being a dead horse. But, to software engineering efforts, pivots are moving the goal posts. Pivots lead to stretching existing product implementations to fit new objectives, to shoving square pegs in round holes. Keep stretching and eventually things break.
- Team Changes. If you inherit a codebase but not the team that wrote it, you probably don’t understand where the tech debt is or how big it is. You also don’t understand the quickest and easiest way to build on what has already come before. Similarly, when you add new people to the team, they typically have a steep learning curve to learn what has come before. In either case, that learning is never perfect.
Particularly Deadly to Startups
Tech debt is particularly deadly to startups because:
- there is enormous time pressure because of funding rounds, meaning it accumulates quickly (and you never have time to address it),
- they tend to pivot frequently, meaning tech debt accumulates quickly (and you never have time to address it), and
- startups are resource constrained so there is little to no bandwidth to address tech debt.
Beware Artificial Deadlines
Sometimes there is a real deadline to ship a product – a trade-show where the product will be launched, or running out of funding being two common examples.
In the absence of a real deadline, creating an artificial deadline definitely has its place. A deadline serves to galvanize a team. It helps stop the team endlessly tweaking and gilding the lily.
However, the hidden cost of an artificial deadline is Tech Debt. Because of the planning fallacy (beyond the scope of this post), software development projects are almost always late so corners have to be cut to make deadlines. That might be ok if you put in place a plan to address the accumulated tech debt immediately after the product launches…but, let’s be honest; that never happens. Tech debt almost always gets kicked down the road because of the pressure to fix defects and respond to user feedback and requests.
Therefore, be wary of artificial deadlines – they have their place but they also have a dangerous, hidden price.
How to deal with Tech Debt
So, now we know what it is, how should you deal with Tech Debt?
1. Understand what it is
Firstly, accept the reality that Tech Debt is a thing. It exists. It’s real and it has to be monitored and addressed. Ignore it and it will get worse and bite you in the rear.
2. Understand where it is
Next, understand how much Tech Debt you have and where it is in your product. If you are not part of the development team, the developers will be happy to tell you; trust me.
3. Prioritize it
Once you know where the debt is and how big it is, it’s time to assess how critical it is to address it. There will always be some Tech Debt – it’s inevitable. Not all Tech Debt is critical to address immediately.
There are no easy answers because the future is not easy to predict. However, here are some rough rules of thumb:
- Tech Debt that exists in core features that differentiate your product and/or which users rely on should be addressed urgently, because you are likely to want to continue to develop those features.
- Tech Debt that exists in any layer of your product which future development will rely on should be addressed urgently, or you’ll be continuing to build on shaky foundations.
- Tech Debt that exists in rarely used features, features that you don’t compete on or features that you plan to deprecate is a lower priority to address.
4. Plan to address it
This might be the hardest part. Addressing Tech Debt will take time. Unless that time is planned and built into the priorities and the schedule, it will not happen.
There is also an associated opportunity cost. You cannot change the laws of physics. Addressing Tech Debt will mean you can’t use that same time to move forward on new feature development. You have to accept that reality.
How to Minimize Tech Debt
You can’t avoid Tech Debt completely – it’s an inevitable part of shipping a product. There is unfortunately no perfect answer here – you have to strike a balance that minimizes Tech Debt but, at the same time, avoids the equal evils of premature optimization, gilding the lily and complete rewrites. Swinging the pendulum too far in another direction will be just as much of a disaster. (Hint: Software is never “done” and, left to their own devices, most engineers would prefer to tinker indefinitely without the annoyance of real users using the product and doing stupid things that they shouldn’t.)
But, just because you can’t avoid Tech Debt, doesn’t mean you can’t take some actions to minimize it:
- Spread awareness of Tech Debt in your organization to make sure you have a common understanding that it exists, that it needs to be dealt with and the dangers of kicking it down the road.
- If you’re not personally involved in the details of software development effort, try to keep your finger on the pulse of the level of Tech Debt is accumulating and communicate that with other stakeholders (particularly the board and investors).
- Always build time into product development schedules to address Tech Debt and factor it into commitments made to customers and investors. Expect to spend a chunk of time/money after each major feature release to address the Tech Debt accumulated during the push to get the feature over the finish line.
- If you inherit a codebase from a prior team or company, make sure you have ongoing access to someone who worked on it originally, for an absolute minimum of 6 months.
- Practice Test-Driven Development (TDD). The details are beyond the scope of this post but good test coverage is invaluable in minimizing Tech Debt.
- Avoid “proof-of-concept” implementations of products and features, especially in a startup where you are very resource constrained. While it’s definitely critical to develop iteratively and build a Minimum Viable Product (MVP) to test if users are interested in your product before you invest too much, you should also assume that all code written will make it into production – you can’t afford to write things twice. This doesn’t mean over-engineer; it means engineer once.
In terms of striking the right balance between being aggressive about shipping products versus premature optimization, my recommendation is that you only make investments that will get you through your next funding milestone or the next 12 months, whichever is later. i.e. if it won’t pay off in 12 months or before you flame out, it’s not worth it.
“Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite… The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation…” – Ward Cunningham, 1992
I recommend you also check out “Lehman’s Laws of Software Evolution“. They started in 1974 so we’ve known about Tech Debt for a while.