On Technical Debt
I’ve created my fair share of technical debt during my career. To be honest, probably much more than my fair share (such is the nature of working at a fast-moving startup). I’ve also paid down technical debt - sometimes my own, sometimes others’. It’s a fickle thing. Too much technical debt and your burden becomes so high you cannot create value, too little technical debt and you probably aren’t delivering value quickly enough. Last fall a friend of mine (who was leading the engineering work at a new startup himself) reached out to pick my brain on the topic. After our call, I decided I needed to write down and share some of my thoughts on the matter. So here goes (albeit 8 months later…).
We should probably start off with a simple definition so we know what we’re talking about:
Technical Debt: the cost of future reworking that results from choosing a quick but limited solution instead of a better approach that could take more time.
From the less experienced, I imagine hearing reactions of “How awful! Why would you make a choice that will ultimately cause you more work down the road?!” They are correct on one thing - creating technical debt does increase the total amount of technical debt that is strictly necessary if you were an omniscient developer (more on this omniscience later). The problem with over-indexing on this perspective though, is that it’s inherently cost-oriented. It’s focused on total time spent. It’s focused on inputs. It misses the key point that you are never developing software for the sake of developing software. You are developing software to solve some fundamental problem that somebody has, and thus create value for them. From this lens, it’s important to ask why anybody would take on technical debt. Let me give you two examples:
Example 1
In a recent post, I provided a passing reference to a great lesson called Tackle the Monkey First. This is often used to discourage people from bikeshedding and instead focus on the existential questions at hand. In this analogy, your team has a great product in mind: a monkey reciting Shakespeare while standing on a pedestal. The easy, straightforward thing to do is to build the pedestal - you know how to do this. The big uncertain thing is to train the monkey to recite Shakespeare. In the post, the author claims that the “right answer… is to spend zero time thinking about the pedestal”. I get the reasons why - you want to hammer down the uncertainty first. But, as explained by Jon Thornton in a great talk at Lead Dev 2023 (great conference, by the way!), there might be other areas of uncertainty that are useful to address quickly. While the highest probability uncertainty is that you can’t get a monkey to recite Shakespeare, another uncertainty that could equally tank the product is whether or not you can even get a monkey to stand on an elevated platform. This uncertainty is actually easy to address, but you actually need to have a raised stand of some kind - a pedestal. So we’re back to the pedestal?! Kind of. You don’t need to build the end-product pedestal at this point - you just need to go to your local hardware store, buy a few 2x4’s, some screws and a sheet of plywood, and throw together a quick platform. Within hours you can learn whether or not the project is doomed to fail - but it requires creating some technical debt.
While the story may exaggerate things a bit, the principle is clear. Technical debt can be a useful tool to reduce uncertainty or learn some key piece of knowledge that will help you on your journey. I call this learning leverage. Just like taking on a home mortgage (at least before interest rates rose significantly) was an assumption of debt, it gave you leverage to start accruing value (equity) as home prices rise and your payments add to your principal. Learning leverage is a trade-off between assuming some technical debt in exchange for something of value, such as knowledge.
Example 2
Let’s suppose you’re a member of startup ABC Inc, developing a great widget that you are sure your target market will love and pay hand-over-fist for. You’ve done some research and determined what problem your target customer wants solved, and assess that you can build a viable working solution within the next three months that will scale to 10,000 users at a price of $100 / user / year. Yes, you’ll have to cut some corners, but nothing terrible. The cost of development over those three months is $100,000 (salaries for staff, compute costs, etc.). To do it “right” would require 15 months, and thus ~$500,000. If you have less than $500,000, the choice is obvious (build and deploy the fast version - doing it the “right” way means your business is no longer solvent). But if you have more than $500,000, it doesn’t necessarily mean you should build it the “right” way. If you did, you’d be losing out on $1M of revenue while you wait. Even if the costs to rework the solution increased by 50% (because you have carry costs of the tech-debt-riddled solution, then teardown costs, and then the build costs of the “right” solution), it still would be more valuable to assume the technical debt, not even accounting for the compounding interest effect of the time-value of money.
Again, this example uses some oversimplifications and simple math to illustrate another clear principle. The focus of your decisions needs to be on value creation. You could of course take a too myopic approach and only consider near-term value creation (don’t do that - you will end up drowning in technical debt), but by focusing on your costs at the expense of your value creation, you will miss the whole point of why you’re working on your problems to begin with. An even simpler way of expressing this point is the following: the best way to avoid technical debt is to do nothing, but of course that means you will create nothing of value.
Conclusion
The key takeaway from this is that we humans tend to oversimplify the world around us. We like to simply label technical debt as “bad” and the lack of technical debt as “good”. In the wise words of Zombie from Wreck it Ralph: “Labels not make you happy. Good. Bad. Rawrrr!” The label of technical debt is entirely contextual based on the surrounding environment and decision process. And don’t forget, you are trying to create value, not just build software.