Tech debt is not a burden, it's a strategic lever for success
reforge.com
reforge.com
Genuine talent tends to recognize and avoid these types of orgs, and the vicious downward cycle you describe seems unstoppable, at least in my experience.
I think the quote that comes to mind for me (as someone who's been with 2 startups now that have grown from less than 20 employees to more than 300) is this:
One man's trash is another man's treasure.
"Good" code written with the constraints of a tiny company won't be "good" code later anyways - the requirements will shift, the company goals will change, focus will change away from some features towards other features, abstraction levels will be different, the quality of your engineers will be different.
Trying to bake in assumptions about what "good" will be 5 years down the line is literally pain for no reason, and I promise you it will be wrong anyways.
Trying to act like the company from 5 years down the line is a guaranteed way to go out of business in the mean time.
In my opinion, investing early on in CI/CD pays so much more than thinking about code quality, correct abstractions and future requirements. If I have a fast deployment strategy with automated testing I can trust, accommodating new features is a breeze regardless of the underlying code quality.
Of course though it's all a balancing act. I could spend a year building a solution using sophisticated tools like spinnaker, only to completely miss the market at a startup. Still, if there is a tradeoff to be made between code quality and CI/CD, I'd always side with CI/CD.
So before fixing other things you need to be able to build it.
So then I think you're saying if you don't fix it, and some percentage of everything you do adds more of it, eventually in the limit you're doing nothing more than some fixed point of progress? 'Take half the previous step forward' sort of thing.
Throwing one more metaphor at it: If you don't scrub the barnacles off a ship, the ship will progressively become more difficult to steer. In fact it will eventually make sense to simply scrap the ship altogether. In software we call it a 'legacy application'.
(Speakers like Simon Sinek have made entire careers out of this specific rhetorical approach.)
In almost all cases, x is both y and z. Such is the truth about tech debt. Tech debt can but a strategic lever for success but is usually simultaneously a burden.
I don't find the examples in the article very on point. Twitter using publicly available storage systems until 2014 doesn't strike me as a form tech debt at all. Rather it is is a logical system design decision based on Twitter's business and organizational focus at the time.
This isn't just true, it's the point of the “debt” metaphor; financial debt is also something used because it is a strategic lever for success but which is a burden once taken on. (It's true that use of the metaphor tends to emphasize the burden part because it is often deployed where the lever of success part is already internalized without regard for downstream cost.)
Embedded is certainly a different world though. The complexity really comes from the fact that 95% of the code is custom, generally poorly designed without tests, and then duplicated and modified over and over again. So rewrites can be very successful in my realm if upper management can be convinced.
But you’re salaried, so it doesn’t matter.
Also people think of tech debt as a loan which is a fine analogy but it’s important to understand it doesn’t map perfectly. Some have a high interest which means your current path is just adding this code debt to more pieces in your codebase (eg a bad convention you know you need to address). Other debt is more sporadic but doesn’t really grow (eg you have to remember to do weird thing X every time you do a Y). It may manifest as a parasitic effect on your velocity (more manual processes and/or more bugs). Additionally, unlike an actual loan balance sheet, there’s no way to quantify any of this. So agreeing on tech debt can even be hard (what one person sees as tech debt another might see as at least having consistency with the rest of the code around it). If you can’t measure then you’re all talking about an amorphous concept no one really agrees on 100% and basically paying down things that everyone agrees on as debt OR getting lucky and finding secondary quantifiable measurements that correlate with what you’re arguing for as debt.
(It's sometimes perhaps more like VC finding - a very high cost for the provided up front money, but only in a small set of circumstances where the overall success makes the cost relatively small)
Software is a leaving breathing thing whose sole purpose is to fulfill a real world intention, it needs constant service, maintenance and upgrade to be kept alive.
At least this is my world view as a product manager of many years (before the term was coined).
You seem to be describing a metaphor more like technical depreciation. Not to be confused with "deprecation." This is not what Ward Cunningham meant.
Here's how I dealt with each:
1) reduced the internal team to half its size
2) fired the offshore team and started from scratch
3) personally attempted a mass refactor / 90 hour weeks
4) refactored 49K line C++/ObjC++ to 29K Swift
Result of each:
1) product shipped, became industry standard
2) Speed improved, Apple offered to feature product
3) I failed, resigned after burnout
4) Easy and enjoyable refactoring to SwiftUI
Better to have a business with some tech debt than no business.
I think we disagree on how much.
And equally importantly management and engineers disagree on “when” to service the debt.
More often than not a product feature gets prioritized over repayment. And management is perfectly happy to have on calls suffer late nights fixing random bugs that proliferate.
Worse is, as time goes on, the knowledge of why a tech debt was introduced vanishes. So everyone gets scared to touch that code with a 100 ft pole.
It’s like building on shaky foundation. Once enough floors are built it becomes impossible to fix the foundation without tearing down the building.
Dirty laundry is never an asset.
If you can borrow at 0.5% and have a fairly reliable system to get 10% returns, is your debt and ability to borrow "dirty laundry" or an "asset"?
Even the code you're proud of is going to need a maintenance lifecycle. If you don't maintain that debt, it compounds to the point you cannot.
Debt is a useful concept because almost every business person understands the risks, but most successful people will borrow anyways.
Where the analogy fails is because we pretend like "if only we pay all the tech debt down everything will be fine". Basically our problem is we think the concept doesn't apply to tech we like.
Most people at my company seem to think tech debt = legacy code that gets in the way of modernization.
Wiki says tech debt is:
"Technical debt (also known as design debt[1] or code debt, but can be also related to other technical endeavors) is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer."
The truth is, maintaining pretty much any tech system is debt. You're going to need to update that code, patch that system, and run that JML process. This will incur an going cost.
Like any corporate debt, you borrow to make profit. If you maintain the debt whilst making profits, everything makes sense and you're good to continue.
If you fail to maintain it, eventually you'll find yourself the unable to make payments and this will manifest as downtime, fines, or an inability to change the software to keep up with the market.
Loans as an overall concept are neither inherently good nor bad.
'Just' a loan? What kind of loan? A mortgage? Or maybe it is like issuing a bond?
It is important to talk about our metaphors in detail. It isn't just the interest rate. It is also about how the debt is structured. Can you pay it back early? What happens when you default? And so on.
Ultimately, the tech debt metaphor should be examined and challenged! It may not 'fit' reality in the ways you might expect.
Blanket statements in abstract, professing the benefits or ills of tech debt lack any sense of nuance.
Less so with technical debt. How do you quantify it? Perhaps we should define a Technical Debt Unit (TDU)? How do you combine two technical debts? Do you add them? What if one compounds the other? So... we multiply them? Wait, that would result in TDU ^ 2. That breaks the units. This suggests that tech debt cannot be represented with a TDU -- or any commensurable unit.
So, money tends to be fungible. Tech debt, not so much.
We can choose our metaphors. Why is the tech debt metaphor so common? Perhaps because it fits the minds and brains of the business decision makers.
Also, businesses recognize financial debt as quantifiable and manageable. It is no surprise that the "tech debt" language is somehow comfortable, even if the connection between the two is on shaky ground.
However, too often, the hard work of conceptually mapping why and how financial debt is useful seems to be waved off.
But perhaps more constructively, I've long harbored the feeling that we are not thinking about the interplay between business and engineering in very useful terms. Phrases such as "tech debt", "culture of shipping" and "product-driven" seem to me to miss a larger point, which is this: there is an inescapable need for semi-undirected, exploratory work. Expecting engineers to always know where they're headed is counterproductive, I think.
In my experience, time spent exploring, refactoring, "paying off tech debt" and other forms of undirected "massaging" of code are significant force multipliers, when performed in addition to planned, focused dev sprints. The reason is simple: manipulating the code base leads to a better understanding of both codebase and domain logic, which in turn leads to better sprint-planning, and therefore faster execution, but also to better products! As engineers perform minor refactors and improvements, they are developing an intuition for which parts of the codebase are pliable, and which parts resist intervention. They can use this intuition to better estimate delays, and better evaluate the utility of new tools and techniques. Once in a while, they may also discover opportunities for improvement, including new product features.
The over-emphasis on "keeping focus" seems to reveal a belief that the product team should set the priorities and that engineers should execute. In some ways, this is a perfectly reasonable approach since it is obvious that the product team is better informed than the engineering team about market, customer demands, deal-flow, and other such business-facing concerns. However, it is also obvious that they are less informed about technical capabilities, i.e. about what is generally possible to do. Likewise, they are also not in a position to make accidental discoveries, and can only direct product development on the basis of known knowns.
I often worry that in an otherwise sensible attempt to keep engineers focused on profitable tasks, this "product-driven" mentality stunts the ability of companies to compete, precisely by setting conditions that inexorably lead to reproducing what already exists. This is especially pernicious for (pre-)Seed and Series A companies, which need to discover their product-market fit, and make durable their differentiation, respectively.
Companies like Google seem to have some (imperfect and perhaps subconscious) understanding of this, as evidenced by the now-famous 20% rule. By spending a significant chunk of time exploring, and bettering things along the way, opportunities for significant improvement are discovered, junior programmers become more familiar with infrastructure and code, the bus-factor increases, and the 80% of time spent on focused sprints becomes more productive. It's inevitable.
However its been terrible for my career. In job interviews people wonder what I've achieved because it really is difficult to prove how you can design and write code. The guys who spend a year or two sh**ing all over the code base as they knock out new features really are doing the right thing. Managers dont care about tech debt, they just want new features.
Founders (technical ones anyway) likely do care about technical debt. They know it could be death to their future ambitions.
Managers have little reason to unless the organization has a sound culture. If they feel like hired guns who may be let go if there is a bad quarter, then their motivations are e.g juice their resume with cool new technology.