Technical debt, also known as tech debt, is functionality or code that needs to be refactored over time. Most often, this end state is the consequence of prioritizing delivery and speed over perfect code. Let’s face it, timeline and budget are real-world constraints. And how does one even define “perfect code”? But as software grows in complexity and size, the effort to remove tech debt grows with it, sometimes exponentially. To ensure maintainability, companies must monitor the amount of tech debt that has accumulated and prioritize addressing it as part of the development plan.

Deliberate Tech Debt

Tech debt can be broken into two categories. The first, deliberate tech debt, is like taking on financial debt through a loan – something is needed now that requires “cash” to pay in full. The instant gratification of advancing the technology (i.e. features, functions, etc.) creates a responsibility to circle back around with code improvements at some future time. It’s a calculated risk taken to achieve a specific short-term objective.

Software prototyping is a common example of this. With prototyping, rapid and incomplete versions of the software are delivered with the purpose of gathering important market data in the short term. That market data is then leveraged to make an appropriate long-term investment in a more complete solution. Deliberate tech debt requires careful planning during development. Teams should anticipate the benefits and tradeoffs of sacrificing optimal design before accepting that debt.

Inadvertent Tech Debt

The second category, inadvertent tech debt, is the unintended side-effect of many different circumstances. The most detrimental circumstance is poor design decisions and inadequate code quality. This debt can be avoided with rigorous standards and strong process. But there are also reasons that are outside a development team’s direct control, like schedule pressure, turn-over and limitations of the adopted framework.

Perhaps the most common factor leading to inadvertent tech debt is the constant evolution of software frameworks, platforms, and infrastructure. If you don’t move forward with it, you get left behind. It’s important when choosing a tech stack to consider the pros and cons. Certain stacks have design limitations that make them better suited for prototyping and similar small-scale initiatives. Others are incredibly versatile, and therefore better oriented for large-scale systems. Choosing the wrong combination can lead to wasted time and budget.

How to Handle Tech Debt

We plan arduously to make sure any debt taken on is sensible. Our project managers work directly with clients and developers to talk openly about the benefits and tradeoffs of various decisions. This back-and-forth enables strong alignment between intelligent design and the clients’ business priorities.

We also have a systematic process to reduce inadvertent tech debt. By documenting design decisions along the way, and referring back to that list regularly, we can hold ourselves and our clients accountable for whatever sacrifices have been previously determined to be appropriate. We offer recommendations that align with the development plan to ensure any effort spent in refactoring is done so with efficiency in mind.

There is also a comprehensive process we follow to ensure our code meets high quality standards on every release. This includes extensive test coverage and documentation of code, as well as code-review by other developers and team leads.

It’s a Balancing Act

Tech debt is a constant balancing act between quality and schedule. And, unfortunately, it’s unavoidable. If you aim for “perfect”, it’s never done. If you aim for “as soon as possible”, you pay a later price with maintainability and scalability. Strong process and regular communication are some important ways to determine what amount is acceptable and sustainable.