Ask 10 people to define technical debt and you’ll likely get 15 different answers. Some definitions of technical debt I’ve read:
- “The result of prioritizing speedy delivery over perfect code.” -ProductPlan
- “The difference between what was promised and what was actually delivered.” - Atlassian
- “The implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer.” - Wikipedia
These definitions often do more harm than good. They imply the development decisions were not well thought out or were simply due to laziness. The reality is more nuanced, and must take into account the business value of the decision at that moment in time.
Technical debt is the cost of having to rework, refactor, or rearchitect a decision that was previously made. That decision may have been made due to speed, budget, or because that was the only option available at the time. Whatever the reason, accruing technical debt is a common practice. Every day, decisions are made that result in accruing more debt.
Technical debt and feature flags
When it comes to feature flags, I’m often asked how you can make sure that adding them won’t result in accumulating even more technical debt.
Forgetting to clean up code or remove a feature flag after it’s rolled out to 100% of users is also not due to maliciousness or laziness. It can often be tied to:
- Not having processes or the right workflow in place to identify old flags
- Lack of visibility into the state of features
- Shifting priorities
For example, organizations may be looking to get features out as quickly as possible. A feature is shipped and the team quickly forgets about it and moves on to the next one. Going back to work on “older” code can slow down the pace of feature deployments. The pressure can seem even greater for seed-stage startups. If you don’t achieve product-market fit or customer validation before you run out of runway, the company fails. There will be time after to go back and clean up the code.
Unfortunately, in many cases, “later” never seems to happen and you end up with flags that are two or three years old and nobody remembers the original purpose of them or what would happen if the code is removed. And the longer the code lives in the codebase, the harder it is to remove. This leads to inertia and the code often stays.
But if a decision is made to remove the code, it’s not just the difficulty of removing the obsolete code, it is also more costly. The delays to innovation can grow as it takes longer to figure out whether the code is needed. A flag that might have taken 30 minutes or less to remove when it was fresh may now take hours of time from multiple people to unpack and remove.
In 2021, LaunchDarkly published The State of Feature Management report. In it, we surveyed over 400 software professionals on their software development and delivery practices. We found that almost everyone is concerned about technical debt, but the degree to which they are concerned varies based on how they’ve implemented feature flags. Only 11% of LaunchDarkly customers reported being very concerned about technical debt, compared to 32% of developers using a homegrown solution.
Best practices around naming conventions—such as including the date, project name, or author in the name—and workflows like quarterly sprints dedicated to removing flags can mitigate some of the challenges related to technical debt from feature flags. But these decisions often occur late in the decision-making process. You need to think about technical debt much earlier in the process. The technical debt you accumulate is decided early on in the decision-making process, when you decide whether you’re going to build or buy a feature flagging solution.
The build vs buy question almost always pops up when discussing feature flags: “It’s just a fancy if/then statement, we can build that.” There are a number of questions you should ask yourself before going down the build or buy path. Here are a few questions you should ask that pertain to technical debt:
What are the unknown costs?
Building something may seem like a less expensive alternative and it’s exciting. But you also need to think about the costs to support the tool, enhance it, train team members, etc. There are many hidden costs when building software and when not considered they can result in the accumulation of technical debt. What often happens is the existing tool that was built doesn’t meet everybody’s needs so different teams go off and build their own solution. And then, instead of having a single tool, you’re now using two, three, or more similar tools.
What happens if you change course?
Change is inevitable. Innovation will continue. And that innovation can lead to different technology decisions. Is what you built flexible enough to grow with you as you continue to innovate? You don’t want the solution you build causing inertia because it isn’t able to support new technologies that are introduced.
Who are the users?
Flags serve many purposes within an organization which means many departments may need the ability to turn features on and off:
- SREs and Ops teams use flags as safety valves. You need to indicate which flags are permanent, operational flags to ensure that they aren’t accidentally removed when cleaning up technical debt.
- After a feature is deployed, product teams determine how it rolls out to the user base, when the beta or canary test is completed, and when it is 100% released. Workflows or integrations are needed to indicate when a feature is fully released indicating the flag can safely be removed from the codebase.
Build vs buy decisions are not easy to make. When considering the best course of action, be sure to think about the technical debt the decision will lead to. Both decisions will incur debt, so go into the decision with your eyes open.