---
title: "Volcanic Minds | Tech debt: a strategic risk for business"
description: "Technical debt is not just bad code; it stifles company growth. An"
url: "https://volcanicminds.com/en/insights/tech-debt-strategic-risk"
lang: "en"
type: "second_level_page"
updated: "2026-09-04"
alternate: "https://volcanicminds.com/insights/tech-debt-strategic-risk"
---

# Tech Debt: it's a mortgage

## How to manage it before it impacts your startup

In the startup world, speed is everything. Launching an MVP before the competition, iterating on user feedback, and growing at breakneck speed. In this **race against time**, phrases like, "_Let's just make it work for now_" or "_The important thing is to go live_," are the norm.

These phrases, familiar to both founders and developers, are the very moment you sign for a mortgage: **Technical Debt**.


## What is Technical Debt? And What Isn't It?

Often seen as the enemy, let's be clear: **technical debt is not a bug**.

A bug is an error,  an unexpected behavior in the software. Technical debt, however, is the result of a choice, often a deliberate one. It’s the trade-off you accept when you choose a **quick-and-dirty** solution today, knowing it will require more work to fix or rewrite in the future.

For example, you take on technical debt when you:

- Postpone **refactoring** to meet a deadline.
- Write code without adequate **test coverage**.
- Choose a **simple architecture**, knowing it won't handle future load.
- Leave **documentation** inadequate, making the code difficult to approach later on.

It's not a failure, but a strategic decision (or a poor one, if made unconsciously). Sometimes, taking on this debt is the right choice to test a market hypothesis and survive. The problem arises when you forget you have it.

## 
Why Is It a Mortgage?

Many of us, unfortunately, understand financial mortgages all too well. Let's apply that concept to code to identify the **real risk**. 

- The **capital:** This is the initial shortcut. It's the time you save today by not writing tests, choosing a simpler solution, or delaying a complex architectural decision. It has its pros and cons.
- The **interest:** This is the future cost of that shortcut. Every time a developer has to touch that piece of code, it takes longer. They have to decipher complex logic, work around the limitations of the initial solution, and be careful not to break anything. This extra time is the interest you pay, and it's often hidden.

Just like a financial mortgage, the interest on technical debt **compounds**. The longer you wait to "pay it back" (e.g. by refactoring), the more the cost of maintenance and new development increases non-linearly. Eventually, the entire system becomes so fragile and expensive to modify that problems become increasingly critical and blocking. Adding a simple feature can take days. This is the point where technical debt can cause a startup to fail or, at the very least, undermine its path to breakeven.

### **Quick code vs Clean code?**

Let's look at a simple, practical example. Imagine we need to display a different **welcome message** depending on the user type (e.g. "Free," "Premium," etc.).

**The "quick" version**
For the MVP, we might write a function like this, directly in the UI component:

```javascript
function WelcomeMessage({ user }) {
  let message = 'Welcome, guest!';
  if (user && user.plan === 'Free') {
    message = 'Welcome! Upgrade to Premium for more features.';
  } else if (user && user.plan === 'Premium') {
    message = `Welcome back, ${user.name}! Enjoy your Premium access.`;
  } else if (user && user.plan === 'Admin') {
    message = 'Admin Panel Access Granted.';
  }
  
  return <h1>{message}</h1>;
}
```

**Why is this debt?** It works, and it's fast to write. But it's fragile. If we add a "Business" plan tomorrow, want to change the messages, or add new languages, we have to modify the internal logic of this component. The business logic is mixed with the presentation layer, making the code **hard to test** and maintain.

**The "clean" Version**
A more robust solution, however, separates concerns. The logic that decides which message to show is isolated in a dedicated module, while the component only handles _how_ to display it. This simple decoupling—regardless of whether the logic lives on the client or server—makes the system easier to maintain, test, and evolve.

```javascript
// file: services/greetingService.js
const messages = {
  DEFAULT: 'Welcome, guest!',
  FREE: 'Welcome! Upgrade to Premium for more features.',
  PREMIUM: (name) => `Welcome back, ${name}! Enjoy your Premium access.`,
  ADMIN: 'Admin Panel Access Granted.',
};

export function getWelcomeMessage(user) {
  if (!user?.plan) {
    return messages.DEFAULT;
  }

  const message = messages[user.plan.toUpperCase()] ?? messages.DEFAULT;
  return typeof message === 'function' ? message(user?.name) : message;
}
```

```javascript
import { getWelcomeMessage } from '../services/greetingService.js';

function WelcomeMessage({ user }) {
  const message = getWelcomeMessage(user);
  return <h1>{message}</h1>;
}
```

**Why is this better?** We've invested a bit more time upfront, but it will save us time in the future. Now, to add a welcome message for a new plan, we just need to modify a dictionary (though it would be even better to use an internationalization system like i18n).


This example is basic, but in a real project, these debts accumulate in hundreds of places, making manual analysis impractical.

Recently, we assisted a major player in the automotive industry with targeted **Code Quality Assessment** activities. The goal was to provide a detailed analysis of a couple of applications containing tens of thousands of files. A completely manual analysis would have been prohibitive, time-consuming and too expensive.

In scenarios like these, where applications are already complex and technical debt hasn't been tracked over time, using automated tools is not an option, but a necessity.

### **Useful tools**

Fortunately, there are **static code analysis** tools that scan your codebase for issues, "code smells," and vulnerabilities, acting as a **financial advisor **for your "mortgage."

- **SonarQube:** A comprehensive platform for continuous code quality inspection. It analyzes code for bugs, vulnerabilities, and, most importantly, "code smells" (indicators of technical debt). It provides detailed reports, estimates the time required to repay the debt, and integrates seamlessly into CI/CD pipelines.
- **ESLint:** In the JavaScript/TypeScript world, this is a fundamental tool. It allows you to enforce style rules and best practices, identifying problematic code patterns as you write. It's highly configurable and helps prevent the accumulation of "small" debt from the start (and let's not even talk about the rampant use of any types, right?).

Beyond specific tools, incorporating automated analysis into your workflow is like receiving a constant report on the **state of your debt**. It makes it visible and _quantifiable_.

### **Managing the debt: strategies to survive**

The goal isn't necessarily to eliminate all debt, but to **manage it**, deciding where to invest time and resources for the highest return on investment (ROI).

1. **Incur debt intentionally:** Taking a shortcut, especially an architectural one, must be an explicit and agreed-upon decision. The team must understand why it's being done and be aware of the consequences.
1. **Create a "debt registry":** It's useful to document technical debt just as you track bugs. Create specific tickets in your project management system (e.g. Jira, Asana) and label them clearly (something like "Technical Debt").
1. **Plan the repayment:** Debt doesn't fix itself. It makes a lot of sense to dedicate a fixed percentage of each sprint or development cycle to addressing it. It may feel like you're wasting time, but it's a crucial investment.
1. **Prioritize repayment:** Not all debt is created equal. Prioritize the debt located in the most critical and frequently modified parts of your application, that's where the "interest" accumulates the fastest.

### Conclusion

Treating technical debt like a mortgage, and not like a series of random mistakes, completely changes the perspective. It's a part of the development cycle, not something that "just happens." You must transform it from a technical problem into a **strategic lever** that a company can decide to use to accelerate, provided there is a repayment plan when appropriate.

A mature technology partner will never promise you debt-free code.

Instead, they will help you understand when it's wise to take on debt to conquer the market and when it's crucial to pause, consolidate, and "repay it," ensuring your startup can run fast today without tripping over itself tomorrow. **The management of technical debt is the hallmark of a company built to last.**

If you need help, we're here for you.


For more information, you can consult the following resources:

- [About us](https://volcanicminds.com/en/about-us)
- [Frequently asked questions](https://volcanicminds.com/en/services/frequently-asked-questions)

## Questions this raises

How to justify the time spent fixing things

### How do you explain technical debt to a non-technical audience?

Through delivery times, not code quality. The sentence that lands is not “the code is messy” but “this change cost three days six months ago and costs twelve now, and we pay that difference on every request”.

**Technical debt is neither an aesthetic problem nor one you can** hand off: it is interest paid on every piece of work that follows.

### How much time should go into debt, concretely?

A fixed, continuous share beats big clean-up operations postponed to a good moment that never comes.

A portion of every development cycle, agreed in advance rather than negotiated each time, works because it does not require asking permission. Extraordinary rewrites almost always come from having skipped that share for years, for urgent matters that never stop arriving.

### When is rewriting better than fixing?

Far less often than the team would like.

Rewriting is attractive because it avoids reading the existing code, but it also throws away years of fixes for edge cases nobody remembers, all of which will come back. It makes sense when the technology is no longer maintained, when it lags badly behind the current one, or when the data model blocks what the business is asking for: in every other case you refactor piece by piece, staying in production.
