The Hidden Costs of Poor Quality Code—and How to Turn It Into a Superpower
Hi, I’m Martin Hinshelwood, and today I want to dive into a topic that’s close to my heart: the true cost of poor-quality code. Over the years, I’ve seen countless organizations grapple with this issue, and the impacts aren’t just financial—they’re deeply ingrained in productivity, team morale, and even brand reputation. Let’s unpack this and talk about how improving code quality can become your organization’s superpower.
The Obvious Costs of Poor-Quality Code
When we talk about poor-quality code, the first thing that comes to mind is bugs. Fixing bugs is expensive, especially when they’re discovered late in the development process. Here’s why:
- Cost increases exponentially: The closer you get to production, the more expensive it becomes to fix a bug. Once it’s in the hands of your customers, that cost skyrockets.
- Customer support strain: Poor-quality code means more issues for your support team to handle, taking resources away from proactive tasks.
The Hidden Costs You Might Be Overlooking
Beyond the obvious, there are hidden costs that many organizations don’t account for:
Brand Reputation
Your product’s quality reflects on your brand. A high-profile example is CrowdStrike, which faced massive global fallout due to poor engineering practices. Here’s what happens:
- Poor-quality products or processes damage trust.
- Customers notice when you cut corners, and your competitors will capitalize on that.
Team Productivity
When teams spend hours firefighting instead of building, it drains morale and efficiency. Common culprits include:
- Complex branching strategies: I’ve worked with a company that had 96 teams and 96 long-running branches, each with its own sub-branches. The cost of maintaining and merging these was staggering.
- Supporting multiple versions: Supporting every customer’s version of a product not only increases costs but also cognitive load on engineers. Fixing the same bug across 10 different versions? It’s a nightmare.
Missed Opportunities: The Silent Killer
Every hour your team spends fixing old problems is an hour they’re not innovating. Ask yourself:
- What features are you not shipping because your team is buried in avoidable work?
- What competitive edge are you losing because you can’t move quickly?
Let me share one of my favorite examples: the Azure DevOps team. They went from needing 72 hours to validate their code to just 3.5 minutes by paying down technical debt. The result? They tripled their productivity, delivering 60+ features to production in a year where they weren’t even focused on features. Imagine what your team could achieve with that kind of efficiency.
The Technical Debt Trap
Technical debt isn’t just about cost—it’s about missed opportunities. Think of it as money left on the table:
- Higher cognitive load: Engineers waste mental energy juggling old and new systems.
- Security risks: When security is an afterthought, it’s expensive—and risky—to fix foundational problems. Hackers love peeling back quick fixes.
The Path to High-Quality Code
Turning poor-quality code into a superpower isn’t easy, but it’s absolutely worth it. Here’s how to get started:
- Reduce Branching
Aim for a simpler branching strategy. Consolidate where possible and focus on continuous integration.
- Limit Versions
Support only the latest version of your product (with rare exceptions). This minimizes backporting and reduces complexity.
- Invest in Engineering Excellence
Prioritize refactoring and modern engineering practices, like:
- Small, discrete unit tests over long-running system tests.
- Reducing feedback loops to catch issues early.
- Bake Security Into the Process
Security shouldn’t be an afterthought. Integrate it into your development process to avoid costly patches and breaches.
A Superpower for Your Team and Organization
When you commit to high-quality code, the benefits are exponential:
- Increased productivity: Your team can focus on innovation, not firefighting.
- Happier customers: Fewer bugs and more features lead to higher satisfaction.
- Stronger brand reputation: Consistency builds trust.
Investing in quality is like paying off a loan—you make small, consistent payments over time, but the payoff is enormous. With high-quality, working software delivered regularly, your organization can achieve its full potential.
So, what’s holding you back? Start investing in your team’s engineering practices today, and watch as your organization transforms.
It’s a lot more expensive than you think having poor quality code. There are lots of hidden impacts. The obvious stuff is the cost of fixing bugs, right? Because you’ve got poor quality and people find issues, and that cost gets exponentially more expensive the closer to production you get, right? More expensive to fix it with the customers. But you’ve also got the cost of customer support. That’s obvious stuff. The things that people generally don’t think of are things like brand reputation, right? What is the impact of poor quality on brand reputation? Not just poor quality in your product, but poor quality in the way you do things.
The most recent one is CrowdStrike, right? They had poor engineering practices that resulted in a massive global impact when something went wrong. All they did was what lots of companies do, which is push something to production and didn’t really think about controlling the blast radius or any of the other modern engineering practices that they might have. So you’ve got loss to your brand. You’ve got productivity of your team, right? If everybody’s got to run around trying to figure out what the problem is because it’s too difficult to figure it out, then you’re going to have a massive loss of productivity.
Not just productivity. There are lots of engineering practices that people use that reduce quality, but they don’t think it reduces quality. One of those is branching, right? Having a really large branching strategy. I worked with a company recently that had 96 teams, and they had 96 long-running branches, one for each team. Then each team created their own branches of that. The cost in lost productivity to maintain that, to ensure that you have a working product, is just enormous. Add to that if you’re maintaining multiple versions of your product, right? This is a massive cost.
In general, you should not be maintaining multiple versions of your product. You should not be supporting multiple versions of your product. You should be supporting the latest version of your product and not anything else. In general, I can think of circumstances where I might have two versions of my product or maybe three at absolute tops. But if you have more than that, perhaps you have a version of your product per customer. That’s a very common one. That’s a massive cost, not just to support and maintenance, but in lost productivity.
If I’m a developer and I fixed a problem, I fixed a bug, right? Let’s take that as an example. I fix a bug in the main version of our product, the latest version of our product, but we realise that it’s in lots of customers’ versions. Maybe there are 10 customer versions that have this bug. Can I fix it the same in all of those versions? Probably not, right? Because they diverge over time, and perhaps things that I used to fix the product as part of the fix in the main version aren’t there in older versions, or it’s slightly different, or it’s not quite the same version. All kinds of that increases the cognitive load on the engineers. It increases the likelihood of something going wrong because you’re increasing that cognitive load.
And because you have to backport all of those fixes across all those different versions, what’s the cost in missed opportunities? Because your team’s having to mess around with lots of work that is avoidable. I’m going to put that in there. These are all avoidable losses in productivity. What are the missed opportunities for your business? What features are you not able to ship because it’s harder for you to add features? A great, fantastic example is some data from the Azure DevOps team. The Azure DevOps team had a very long tail on figuring out whether they’d been successful in building the product, right? The engineers had been successful in the code that they write and having the test and validation of those things done, and it was taking 48 to 72 hours to figure that out.
They invested a bunch of time and energy in paying back poor choices they’d made in the past, some of them deliberate. That’s okay, but poor choices they’d made in the past and things they didn’t realise were poor choices in the past that they now realise were poor choices. Paying that back took them nearly four years of investment in that story to fully pay it back, right? You know, just like if you take out a loan, you pay it back over a longer period of time, a little piece at a time. So they were paying it back as they had time. They were prioritising it, so it was important to them. They were spending time on it, but they were also doing other things, so it’s getting done over time.
So it took them four years to pay it back, but that, plus fixing that problem, refactoring that problem, re-architecting that part of the problem, so they went from 72 hours—that was the longest—to find out whether you’d broken stuff to three and a half minutes, right? So that’s a massive shift. Shifting from long-running system tests to small discrete unit tests as their measure of validation massively impacted their productivity. They went from 25ish features to production each year with 650 people to over 800 features to production with the same 600 people. Not quite the same, right? Because it’s four years’ time, but more or less the same 600 people.
Even in the first year, when they had a really big focus on paying that back, although there was a long tail, a really big focus on paying it back, they spent most of their time in the first year focusing on fixing a lot of these types of architectural problems. They weren’t focused on features, and they still managed to go from 24 features to production to like 60-something features to production—almost three times the number of features were delivered to production at the end of the first year, and they weren’t even focused on delivering features. They were focused on building up engineering excellence, fixing those older problems that had crept in over time.
You know, it’s like 15 years working on this product, and it had this massive, massive boost to not just productivity, right? The productivity of the team, but brand reputation went up because you’re delivering more features, more experiments, more things that your customers need. You’re missing fewer opportunities, and you’re having fewer security breaches because if we’re iterating much more quickly, which is what you’re trying to do, is reduce those feedback loops. You can’t leave security to the end. One of the main reasons that companies get large-scale, high-cost security breaches is that they leave security as an afterthought. It’s not baked into the process.
If security is an afterthought, you find a problem in the way you’ve architected your product. It’s a lot of work to go back and fix that, so most people in teams don’t because it may be hundreds, thousands of hours to go fix it. Or we could get out the sticky tape and super glue and stick over the top and create something over the top that prevents the hackers from getting into that flaw. But hackers spend copious amounts of time figuring out how to peel back the edges of those sticky things and get underneath and get access to the system.
So by paying back this technical debt of increasing the level of quality in your product, you have all kinds of exponential benefits to your ability to deliver product to your customer, the happiness of your customer, and you’re able to not just reduce costs. Technical debt is not just a cost; it’s a missed opportunity. Right? What money are you leaving on the table because you haven’t had the ability to tackle those opportunities? You haven’t had the ability to try those things. This is fundamentally why having high-quality, usable, working product on a regular cadence is a superpower for your teams and for your organisation in your ability to deliver value.