We’ll figure that out when we get there!

Over the years in my experience, I’ve seen teams often treat technical debt as purely negative (Once, I was one of them). Engineers complaining about shortcuts taken in the MVP phase, product managers complaining about the low velocity of feature delivery… And list goes on!

I wrote this article to break the negative perception of technical debt, connect the dots, and share my perspective — so you can enjoy reading it, and I can revisit it and refresh my thoughts in the future.

Please note that Technical Debt is a very deep topic by itself and there are books and research dedicated to it. This article is an introductory guide for raising awareness and classifying technical debt at the team level. It focuses on awareness, basic classification and practical steps for managing debt. The content is most relevant for small teams.

What is Technical Debt?

The term “technical debt” is coined by Ward Cunningham in 1992, according to the Wikipedia. The concept, Technical Debt here is compared to financial borrowing, just like loans. With the loan we take, we can invest in our business and grow it. Consequently, we are expected to pay it back in the future, typically, in monthly installments.

Similarly, in software engineering, we can take shortcuts today for faster delivery, with the expectation of paying back later through regular refactoring or redesign.

So, debt isn’t inherently bad in both financial and technical contexts. It is strategic.

So what is bad about it?

It is bad if we don’t manage it well. In financial terms, if we take on too much debt without a plan to pay it back, we can end up in a difficult situation. Eventually, it may lead to bankruptcy.

Similarly, in software engineering, if we accumulate too much technical debt without addressing them, in the long run, we may face bankruptcy and have to choose either a complete system redesign or abandon the project altogether.

Indicators of Technical Debt

Unmanaged technical debt doesn’t stay hidden. It shows up in various ways. Here are some common indicators:

  • Frequent bugs, errors and failures
  • Low agility and speed in delivery (low velocity)
  • Constant firefighting
  • Increased technical complexity
  • Certain tasks become pinball balls among engineers - Not easy to understand, too risky to touch!

If debts are not addressed, they can snowball into larger issues:

  • The refactoring tasks waiting for some time in backlog become reworks as other features are built on top of the quick solutions.
  • Higher rate of incidents and outages
  • More feature is now implemented with workarounds and hacks
  • Bankruptcy! - A complete redesign or abandonment of the project.

Categorization of Technical Debt

Technical debt can be categorized in various ways based on perspective. I find it helpful to think about it in three main dimensions:

  1. Categorization by origin: A basic way to distinguish between intentional, unintentional or unavoidable debt.
  2. Categorization by origin & behavior: Examining how the debt manifests in the codebase and team dynamics using the Technical Debt Quadrant.
  3. Categorization by risk & impact: Assessing the potential consequences and issues arising from the debt.

1. Categorization by Origin

A. Intentional (Planned)

Intentional Technical Debts are deliberate decisions to emphasize speed of delivery over quality. Time-to-market pressures often drive these decisions. In other words, this kind of technical debt that occurs when teams (had to) take a shortcut to deliver the product with an agreement that they will come back and improve the technical quality later.

This scenario is mostly seen when building an MVP of a feature. So, strategic reasons; just like loans. This is the positive perspective of Technical Debt. But only if you keep your promise to pay back on time. Ideally, once the feature proved itself and the core idea is validated, the team should allocate time and resource to improve the technical quality, before it gets any dependents. So, build, measure, learn then if the feature proved itself, pay back your technical debt.

That said, there are certain things that should never be subjects to Technical Debt, in my opinion. Such as security and automated tests.

B. Unintentional (Accidental)

Unintentional Technical Debts arise from lack of knowledge, experience or awareness. These debts are not planned and often result from:

  • Poor design choices
  • Lack of documentation
  • Inadequate testing

C. Unavoidable (Inherent, natural)

Unavoidable Technical Debts are a natural part of software development. They arise from circumstances beyond the control of the team. It occurs when there are constratints, limitations or external factors and typically cannot be eliminated entirely. Some examples are:

  • Complexity of the business
  • Changing requirements
  • Internal legacy dependencies
  • 3rd party dependencies
  • Compliance & regulations
  • Evolution of techniques, tools, technologies, dependencies

P.S. This category is not a formal classification. In my opinion, the outlines I mentioned above are not covered either in Intentional or Unintentional Technical Debt. Therefore, I believe it deserves its own recognition and management strategies so I prefer recognizing “Unavoidable Technical Debt” category and examine the related topics under it.

Categorization by origin & behavior (Using the Technical Debt Quadrant)

The Technical Debt Quadrant is a framework introduced by Martin Fowler to classify different kinds of technical debt. The idea is that, it introduces 2x2 model that categorizes debt along two axes. It doesn’t only help teams to understand the category of debt (X-axis) but also team’s behavior towards managing that debt (Y-axis).

You may find it overlapping with the first categorization style above. Here, the focus is on the team’s awareness and intent regarding the debt.

                             Deliberate                          Inadvertent
                           (Intentional)                       (Unintentional)
                  +-----------------------------------|-----------------------------------+
                  |                                   |                                   |
                  |                                   |                                   |
                  |  Shortcut debt: knowingly cutting |  Negligent debt: sloppy design or |
     Reckkless    |        corners with no plan.      |           ignorance.              |
                  |  (We don't have time for design!) |       (We don't know how!)        |
                  |                                   |                                   |
                  |                                   |                                   |
                  +-----------------------------------+-----------------------------------+
                  |                                   |                                   |
                  |                                   |                                   |
                  |  Strategic debt: conscious, with  |   Learning debt: design choices   |
     Prudent      |             a plan.               |   made with incomplete knowledge  |
                  |     (We'll deal with it later!)   |     but later improved.           |
                  |         (Honest promise)          |   (We shouldn't have done this!)  |
                  |                                   |                                   |
                  +-----------------------------------|-----------------------------------+

A quick overview of the four quadrants of technical debt:

Quadrant Description Considerations
Deliberate & Reckless Knowingly taking shortcuts without considering consequences or planning to fix them. Adapt culture to prioritize quality and long-term thinking.
Deliberate & Prudent Intentionally incurring debt for strategic reasons, with a plan to address it. Follow through on the plan and ensure the debt is paid down on time.
Inadvertent & Reckless Unintentionally creating debt due to lack of knowledge or care. Improve the technical knowledge of the team and if possible, implement safeguards to prevent recurrence.
Inadvertent & Prudent Debt incurred by mistake or as a result of a change in requirements. Document the lessons learned and share them with the team. If applicable, implement safeguards to prevent recurrence.

3. Categorizing by Risk and Impact

Not all debt is equal in the sense of risk and impact. Some issues only affect code readability; others block scaling, agility or introduce security vulnerabilities. This categorization helps prioritize based on severity.

  • Cosmetic: Stylistic inconsistencies with minimal impact.
  • Growth-Limiting: Anything that slows developer velocity or prevents scaling.
  • Critical: Impacts reliability, performance or security.

Managing Technical Debt

We now have a clearer understanding of the Technical Debt concept. Now, let’s dive into managing it.

Regardless of the size of the project, technical debt is inevitable. Meaning that we cannot eliminate it but we can manage and mitigate it.

Here are the strategies to manage technical debt that I have found effective.

1. Create awareness

First thing first, we must make sure that the entire team knows that there is such thing as technical debt. Everyone understands what technical debt is, why it matters and how it impacts the project. Might be helpful to add it in your onboarding materials.

2. Keep a Technical Debt Registry

In order to fix something, first, we have to be aware of the problem’s existence. It is important to increase the visibility of technical debt. And, Technical Debt Registry here comes into play. Technical Debt Registry is a centralized place to log and track technical debts. Technical Debt Registry can be a dedicated tool, issue tracker (e.g. Jira) or a simple spreadsheet.

You can choose to create tickets to track your technical debts in your issue tracker. However, in my experience:

  • Technical debt tickets can sometimes be overlooked or deprioritized in backlog, in part because issue trackers often separate the technical context from product priorities.
  • Creating a ticket for newly discovered debt while working on a task can require multiple steps. Adds friction that discourages reporting.
  • It’s often hard to get a clear view of overall debt status.

For these reasons, I prefer maintaining a dedicated spreadsheet (e.g., Google Sheets) as a Technical Debt Registry. It’s easy to access, update and understand. Allows the entire team to contribute their findings quickly on the way while working on their tasks. Ticket can be created for an entry from the spreadsheet once the team agrees on the priority and solution.

Here is a Technical Debt Registry template that should be sufficient:

Description Risk Category Potential Solution(s) Reported By Owner Created At Status
Hard-coded feature flags in new Promotions MVP Service Growth-limiting Once the MVP is validated, replace with centralized feature-flag service John Jane 16.06.2025 On hold
Misleading error logs in many services. Example: {link} Growth-limiting Improve logging format and add context when coincided Jane Everyone 02.07.2025 In Progress
Inconsistent coding standards across modules Cosmetic Establish and enforce coding guidelines {link to draft guideline}, automate Jane Jane 16.08.2025 In Progress
No rate-limiting in API endpoints Critical Check the past usage patterns, align with the customer onboarding team and determine a fair usage policy John ? 20.08.2025 To do
3. Encourage ownership

Foster a culture of collective code ownership, where team members feel responsible for the quality and maintainability of the entire system.

Hold regular Tech Council meetings where each team member is welcomed to take the stage and share their ideas and solutions for any of the technical debts in your Technical Debt Registry. If they want to take the ownership, create a ticket during the meeting with the agreed solution and outcome and then let them have their fun! This encourages collaboration and shared accountability for managing technical debt.

4. Automate and Measure

Leverage your CI pipeline for technical debt management tasks that can be done by machines statically. You can program your CI pipeline to enforce:

  • Coding standards and design guidelines via static code analysis and linting tools (Cosmetic debts)
  • Test coverage (Growth-Limiting, Critical debts)
  • Upgrading outdated dependencies (Growth-Limiting)
  • Eliminating dependency security vulnerabilities (Critical debts)
5. Measure

Use metrics and measure the technical health of your system such as code quality, test coverage and dependency freshness.

Metrics to keep an eye on shouldn’t be limited to just technical details. Consider also tracking development velocity and bug/incident rate. When combined with technical metrics, these can provide a more clear picture and makes it easy to translate the situation into business impact (cost, time, risk).

For example, increasing bug rate can be explained by declining test coverage rate. And combination of these two metrics may suggest that quality is being compromised in favor of delivery speed.

6. Opportunistic refactoring & Boy Scout Rule

This opportunistic refactoring is often referred to as following the camp site rule - always leave the code behind in a better state than you found it. If everyone on the team is doing this, they make small regular contributions to code base health every day.

says Martin Fowler in his article, Opportunistic Refactoring.

Similarly, Eric Evans mentioned the Boy Scout Rule in his book, Domain-Driven Design (If memory serves correctly.)

Both emphasize the importance of leaving the codebase in a better state than you found it.

If you identify a code-smell somewhere in the same file you are currently working on, don’t ignore it and refactor it. Same goes to a missing test case. It probably won’t take longer than 10 minutes.

That said, don’t let this small refactor sneakily lead you to a rabbit hole. It can lead to discovering larger issues that need to be addressed separately.

7. Balancing Delivery and Sustainability

Delivery here represents product / feature and sustainability represents the long-term health of the system.

It’s important to have a plan for repayment strategy. And the crucial part of this plan, in my opinion, starts with setting aside time in sprints specifically for addressing technical debt. Allocating 10-30% of each sprint to debt repayment is always a good idea. This balances delivery and sustainability.

Aligning debt strategy with business goals is also important. A startup, for example, may tolerate more debt for speed. But this must not mean ignoring the technical debts altogether.

Debt is not just a technical concern, it’s a business risk. So it is important to communicate openly with stakeholders. One challenge here is to explain tech-related debt in business terms, in ubiquitous language so non-tech-savvy stakeholders can understand clearly. Explaining with metrics and potential impacts to the business can help make the case.

Another important aspect to keep in mind is that paying it off too early can waste effort if the assumptions in the MVP haven’t been validated. On the other hand, delaying repayment can block critical features or introduce operational risks. The key is to find the right time to address it.

When finding the balance, the team should consider the potential impact and estimate the total cost of ownership (TCO), the total cost of maintaining a system over its lifetime. For example; the pricing table of distributed serverless functions that cloud vendors release on their front-pages might be enticing and sounds cheaper than your existing n-tier monolith running on a few compute units. However, when learning curve and operational overhead in daily development routine factored in, it can be more expensive than your existing monolith architecture.

8. A safe stage for sharing

The rate of change in tech today is way faster than ever before. Therefore, keeping an eye on the evolution of software engineering is crucial for every team. We, engineers are curious by nature, so this is still unlikely to be a problem. The problem arises if we won’t create a space that encourages sharing and collaboration.

It’s a good practice to create a stage and let everyone share something that they found last Friday night along with cups of coffee. The topic doesn’t always have to be in the scope of your Technical Debt Registry entries. The idea is to instill a continuous learning and knowledge sharing culture.

And finally, don’t underestimate any ideas or proposals of your colleagues. Decisions mustn’t be made by a single person or a small group in isolation. This discourages the collaborative spirit that is essential for innovation and improvement.

Don’t underestimate the proposals of your colleagues

Last words

Addressing and mitigating technical debt is not just a matter of coding efficiency, it’s an investment in the long-term success and sustainability of the project. Treat it like financial debt: borrow deliberately, track it transparently, and pay it back before the interest becomes unmanageable. Teams that balance short-term velocity with long-term sustainability can maintain a healthy engineering culture while continuing to deliver business value.