How to Deal With Technical Debt?
Having technical debt is 100% okay. For example, it’s a natural “legacy” of many companies that rush to bring a satisfactory solution to the market. This allows them to start making revenue and collecting user feedback early, so they have enough resources to address these issues in the future. Done is better than perfect, right?
In fact, based on McKinsey’s research, 70% of companies spend 6-20% of their annual budget on “paying off” technical debt. Moreover, ScienceDirect reports that even large well-organized companies allocate 25% of the whole development time (on average) for managing tech debt. But the thing is that each company defines technical debt differently.
As we’ve said, the widespread definition of it is the result of preferring delivery speed over perfect code. Yet, apart from time pressure there are many other causes of technical debt accumulation — it can be delays in refactoring, new technologies occurrence, lack of technical knowledge or code documentation, budgetary restrictions, etc.
Even though there are some techniques to prevent technical debt from accumulating, sometimes it can get out of hand. That’s when it can no longer be ignored and requires more proactive approaches to be dealt with.
In this article, we’ll talk about ways to handle the debt, share our experience of covering it for our clients, and give you a step-by-step guide of what to pay attention to when preparing to tackle it.
📊 Approaches to Handling Tech Debt
There are 3 main ways to handle technical debt:
- rewriting the whole code;
- continuously improving the codebase (refactoring);
- and a mixed approach (some of the parts are better to rewrite while others simply need a little modification).
Rewriting the whole code
Rewriting the code might be reasonable when the technical debt is so massive that it’s much cheaper, faster, and more efficient to simply rebuild the product. Apart from a huge debt, reasons can be the following:
- You want to change the tech stack that your product is written in. Let’s say that instead of offering an app for iOS only, you want to build a cross-platform solution using the same codebase with React Native. You can learn more about migration from one platform to another in our iOS to Android app conversion article.
- Your product/MVP was built by developers who you’re not working with anymore (and aren’t planning to do it again). This can be the case if the product was built using some technologies that are not widely used anymore and now it’s difficult to find an appropriate developer with the same skill set to maintain the codebase.
- An upcoming update would be drastically different. For instance, design remake, UX structure modifications, etc.
- Your database’s structure doesn’t meet new requirements or is poorly organized. For example, if you store the data without any separation (that is, all at one space), it exposes you to more difficulties like problematic data filtering and sorting, being unable to find data without additional time-consuming actions, etc. All of it damages the performance and increases processing time.
Refactoring as a Way to Reduce Technical Debt
Another approach to repay technical debt is to modify the existing codebase. You should opt for this option if there are no significant changes, it’s probably not worth it. Let’s take a look at some particular reasons:
- You need to deliver new features as quickly as possible. In this case, refactoring is often done on the go: developers fix some parts of the code while implementing new functionality. Often companies even consider this when making an estimate, adding an extra 20% of time for refactoring.
- Small database structure changes (that was initially well-organized).
- Insignificant performance problems like excessive re-rendering that causes visual defects & others. For this you may need to improve the way you work with data, implement best practices of the framework, etc.
One more way to handle technical debt is a hybrid model where a part of code is worth rewriting while some of it will be decent with just a little improvement.
For example, it may be the case when you need to fully rebuild your BackEnd while just slightly modifying the FrontEnd. Also, this approach is often used when working on products with microservices architecture.
Such a model is quite easy to define — if you can apply use cases from the first way to one part and those of the second one to another, you should opt for this model.
🤖 How to Manage Technical Debt: Our Expertise
As a development company, we have a lot to do with handling technical debt for our clients and have assembled quite a lot of experience that we’ll gladly share with you. By getting acquainted with our cases, you might get some ideas for your project and prevent certain mistakes in the future.
We’ll give you a couple of examples for each covering approach.
Complete Rewriting ✏️
A team that was working on this project before we took it over set up CI/CD (Continuous Integration/Continuous Delivery) using already deprecated versions of the libraries. The platform that this team used for the setup announced that these library versions would be supported for a limited time. It was the signal for the development team to update it during this period to prevent troubles.
However, previous developers failed to seize the moment and didn’t perform the update. After some time, we took over the project and started to deploy the backend code using the existing CI/CD configuration. Everything was fine for some time, yet, the code suddenly wasn’t able to pass certain deployment stages. As a result, we couldn’t release new product updates.
Our team was trying to fix the problem locally but then we realized that the platform simply stopped supporting these library versions. The only reasonable solution was to fully rewrite the CI/CD process since it wasn’t possible to change the code on the failing steps only.
This case is a great example of how technical debt can occur due to a lack of attentiveness to changelogs that each platform provides. Such troubles can be easily prevented if your development team keeps an eye on things like this and doesn’t dismiss them.
There was another case where the backend was fully written in Scala, which is quite a rare language to use as of now. As a database, they used MongoDB. It was quite an (unnecessary) challenge to support the product in the way it was. Thus, to prevent future problems and needless expenses, we’ve decided to write our own server with NodeJS.
At first, we connected it to the old database and were gradually transferring parts of the old server to the new improved one. Once our server was able to process most of the requests, we started rewriting the database as well. In the beginning, we were sending the data to both servers but eventually shut down the old one.
Continuous Improvement 🔨
Such a tech debt handling type is something rather inevitable. This is why there are multiple cases that can be used as an example. We’ve selected the most representative and diverse one.
We’ve got to work with improving the digital product’s code:
- Navigation modifications like adding new screens and tabs, which lead to rewriting navigational patterns.
- Libraries and configurations updating. The provider changed the way of accessing the platform. Due to this, we needed to update the library so the product could work properly.
We’ve also had to take care of improving the backend code in multiple aspects. For instance, architecture changes like making the entity scalable, preserving backward compatibility and data integrity when updating the system while satisfying the requested business logic.
Moreover, there were cases where we performed system localization (for products that didn’t initially imply such a process) and integrated third-party services.
Mixed Approach 📋
One of the most widespread cases of such an approach that we had to handle is a well-functioning frontend with almost 0 critical issues (design is suitable and the whole workflow is stable) with a problematic backend that has data processing troubles.
In such cases, fixing the “bad” backend would require rewriting a lot of other backend-related aspects, which is why coding it anew would be a lot cheaper and faster. At the same time, the frontend gradually gets updated as you add new functionality.
✅ Our Approach to Handling Technical Debt: General Tips
If you need to handle technical debt for your product, the first thing you need to do is to collect the maximum amount of information possible. As obvious as it sounds, it’s not always easy to ask the right questions.
To provide you with a template of what you should pay attention to, here’s what we start with when asking our clients regarding their technical debt or handling it for ourselves:
- What is your maximum budget?
- When are you planning to deploy the new version?
- What exactly do you want to change in design?
- Do you want to add 3rd-party integrations?
- Will the functionality change? If yes, what features are you adding or removing?
- Do you need to modify/expand the codebase?
- What are the versions of the libraries you’re using?
- Are you considering changing the framework? Why?
Most likely, you won’t have answers to half of these questions straight away but it’s totally fine. Take time to do your own examination and note all the issues along with possible solutions that come to mind.
Additionally, it can happen that you can start working on your technical debt with the permission of C-level employees only, but they might not have the sufficient level of technical knowledge to understand the importance of covering it. In such cases, we’d recommend addressing the issue from the point of value. That is, what the company will get after handling technical debt:
- Increased velocity. With a technically well-functioning code, you can deliver updates and modifications significantly faster.
- Better user experience. Additionally, it directly influences potential income in a positive way.
- Higher efficiency. You can save resources on some things that you previously have to take care of.
All in all, technical debt isn’t just a burden that you need to carry — it’s a wonderful opportunity to implement collected feedback from your customer to provide a better user experience and thus, be more attractive to potential customers.
If you have any questions on covering the technical debt left or need the help of an experienced development company with it, feel free to reach out to us!