What’s Technical-Debt-Driven Development?

What’s Technical-Debt-Driven Development?

Or TDDD for friends and family

How many times have we been pushed into working on a feature because, and I quote, “It’s now or never. If we don’t change this now, it’ll be too expensive to change in the future”?

This is the premise of this article. Whether it’s because of a deadline, a lack of knowledge, or maybe even faulty requirements, sometimes we tend to cut some corners when writing our code, and that leads to future problems and the classic //TO-DO: Fix me comment that never gets resolved.

If we’re lucky enough, we might be able to tackle some of those to-dos in the future, but are we really going about it the right way? Why do we generate technical debt in the first place? And most importantly, can we avoid it?

What Exactly Is Technical Debt?

Saying our project has incurred technical debt makes it sound like we owe something to someone, and it kinda is the case: We owe technical correctness to ourselves.

Let’s put it this way: Just because a piece of logic works right now, it doesn’t mean it’s ready for its intended final use case. If we’ve created a PoC that “works” under a set of very detailed restrictions, we should not let it go to production because we know it wasn’t designed with that aim in mind. Then why do we let it happen time after time? I know, sometimes it’s not like we have a choice; sometimes it’s more of a business decision that supersedes our warnings. But moving fast should not be an excuse for bad system design or even bad coding.

It is also our job, as experts in our field, to make everyone who’s unwilling to listen understand the repercussions of moving forward with a piece of code that is not yet ready.

So essentially, technical debt is the bag of problems we’re building ourselves by using code/logic/an architecture that is not yet ready to be used under the current circumstances.

We keep saying “we’ll fix it later,” but that might not be possible. Consider a full product built around a poorly written library. What happens once you fix everything that was wrong with the library, and you now require a completely different architecture to use it? Do these improvements really justify rewriting the whole product? The answer is usually no, which means you tried to reduce your tech debt too late. Welcome to the club!

It’s a fine line we as developers have to walk. On one side we’re too relaxed about the implications our bad code will have for the future, meaning we probably don’t really care about that. And on the other, we’re seen as the person shouting “the end is nigh!” on the street, ignored by everyone passing by. We need to walk the line between both worlds to make sure we’re not ignored.

What Causes Technical Debt?

Aside from knowing what is it, what exactly causes technical debt? And more importantly: Can we avoid it?

I personally don’t think you can avoid having a certain degree of tech debt in any project. This is because you’re not usually developing in isolation. Your work is part of a pipeline designed to release a product or a feature into an existing market. That market has a demand, and the best interest of your client is to meet it sooner than later. This is just a fancy way of saying the real world will tend to push you towards skipping corners. And trust me, you can’t fight the real world and win, so instead embrace it. Accept that you’ll have to deal with a certain level of tech debt, and make sure you make time in the future to address it.

It’s all about balance.

Outdated tech

Probably one of the most common ways of incurring technical debt is by utilizing outdated technology as part of your project. Whether you were aware of it or not, or the tech got outdated over time (like having a web app that only worked for IE 6) you now have a problem.

Whatever your code is doing, if the technology behind it (whether it’s the programming language, the platform it’s running on, the communication protocol, or anything else) is no longer valid, you’ll start having problems.

Perhaps you’ll notice that your platform is unable to serve all your customers because it can’t scale. Or perhaps you’re using a programming language that no one knows anymore (*cough* COBOL *cough*) so finding devs to work on it becomes difficult and expensive. Or perhaps the way you send data back and forth is adding a huge amount of latency to the communication and coupled with the increased traffic your application is providing a terrible user experience.

I mean the consequences of this type of technical debt can take any shape, really. But the end result will be the same: Your solution will be replaced by something that works better and provides a better user experience. Whether that new solution is also yours or the competition’s is up to you to decide.

How can you avoid using outdated or deprecated tech? That’s a tough one, buddy. To be honest, nobody can predict when a piece of technology will be deprecated. You can definitely try to avoid using already deprecated technology — like trying to use SOAP for your communication’s protocol when REST or even GraphQL are already available. If a piece of tech was deprecated by the industry that means there is at least one replacement that is better, so you’re better off using that.

Incrementally adding changes

There is nothing wrong with incremental modifications, not as long as they’re done with care for quality, not only speed.

It’s a very different story to patch your code quickly because it’s a Friday afternoon and your fix needs to be in prod in the next ten minutes. When that happens you’re likely to add faulty — or let’s call it “less than ideal” — code, but you should fix that patch next Monday.

If you leave that patch there, the next time you have to add another fix, the code will already have a subpar quality and you’ll be adding on to that. In this scenario the sum of subpar quality patches only diminishes the overall quality of your code, so do not let a hacky patch go unchecked for too long.

Let’s be real for a second: We’ve all written a terrible, hacky patch at least once in our career, and that’s fine. The real world always creeps in and forces our hand. That’s not the issue here; the problem — and thus the tech debt — happens when we don’t do anything to fix that patch a few days later (or whenever we have some time available). Because if we don’t, the next time we’re forced to add another patch, the quality will decrease a bit more, and that will continue until it becomes a snowball of patches and our code becomes unwieldy and very hard to maintain.

How can you avoid it? Take the time to fix the fix. That’s it. This is probably the easiest type of tech debt to avoid. Make the time to update the patch you added and make sure the code quality doesn’t diminish because of it. That can take the form of a new task within your sprint or maybe a quick detour as part of your current task (ssshhh, nobody needs to know!). The point is: Fix the fix.

Quick win vs. future thinking

Everybody loves quick wins, especially the business. The moment they can show clients how great the product is, or rather, is going to be once it’s finished, the better. A quick win is essentially the culmination of a quick effort from the dev team to deliver a single feature that provides value to the user (i.e., the paying customer).

Now, for you to deliver that quick win, you — and most likely your entire team — had to focus on a single feature without paying much attention to how it would fit within a larger context. In other words, you had to skip some corners to provide the feature. Whether it’ll work like it was written once you add the rest of the product’s pieces around it, that’s a whole different story.

This is yet again a case of “real world” vs. “product plan.” Sometimes for you to finish the product plan, you need backup from the real world (in the form of financing, for instance). So who wins? The real world wins every time, that’s who wins.

The problem, then, is to work on the quick win while also remembering that this is just a small part of a bigger whole. That way you keep the vision in your mind while making design decisions.

For instance, pretend you’re working on a set of microservices that will be deployed as part of a cloud-based platform. But right now the business requires a quick demo, so you grab your services’ code and decide to put it all together as part of a single project consumed by client code in the form of a monolithic application. That sure reduces the time required to deliver the quick win. However, you cut so many corners that your final code will not be portable into a cloud environment, not unless you also refactor it.

How can you avoid this tech debt? You can’t avoid quick wins; that’s just a fact. You can’t beat the real world, so instead, try to manage the expectations. A quick win can’t be the whole product, nor it should mean you’ll cut so many corners that the final version will be a different product altogether. Instead, try to narrow the scope and keep the final goal in mind when designing how to structure this code.

Another alternative would be to treat this quick win as a throwaway piece of code: something that can be demoed but that is not part of your main development effort nor something you will continue working on once the demo is over. This is a dangerous route to travel because it potentially means a lot of dev time that can be considered wasted. But then again it can also be the best tech decision you make.


If you liked what you’ve read so far, consider subscribing to my FREE newsletter “The rambling of an old developer” and get regular advice about the IT industry directly in your inbox


A greedy mindset

Finally, the last type of tech debt I want to cover is one due to lack of vision. In other words, it’s taking a greedy approach to designing a product.

A greedy approach would be one that only takes into account the current needs of the users. For instance, if you’re building a chat application for your company’s IT department, a greedy approach would be to design it as desktop apps for Linux, which is the OS they’re all using. The rest of the company is Windows-based and could’ve also benefitted from having a similar application, but you were just too greedy to look elsewhere and see potential use cases for your idea. Thus you designed a system that is incompatible with your other users. If tomorrow you’re asked to extend the reach of your chat application to other sectors within your company, you’ll have to deal with this tech debt.

Another way of looking at this type of tech debt is from the “it needs to work yesterday” type of mentality. Often times we’re faced with ridiculous development times because projects are sold only taking into account commercial interests — the good old “if we finish this project now, we’ll be able to sell ten other projects to this client.” So instead of getting the correct amount of time to properly finish the project, you’re forced to cut some corners and deliver on time. And while the product might work, the internal quality and its maintainability might be questionable.

How can you avoid it? Or at least keep it under control? By trying to help the business keep an eye on the goal. Granted, their goal might be “making more money,” but it should also be “delivering quality products” and you can’t do that by constantly cutting corners. It’s not an easy conversation to have, but consider this: A well-designed and thought-out system can be easier — and thus cheaper — to extend than a quickly delivered, half-assed one. Going back to the chat app example, if whoever designed it had thought about other potential customers, maybe going with a cloud-based web application could’ve saved a lot of time and rework when making it available to other sectors of the company.


Technical debt is something we have to be comfortable living with as part of our career, but not too much. It’s like drinking wine: A little sip here and there is perfectly fine, but a couple of bottles a day might be a problem.

In all seriousness, knowing how to deal with technical debt and even the simple fact of taking it into consideration when making a decision are the signs of an experienced developer. It also shows you care about the quality of the delivery, which is an even more valuable skill than, perhaps, knowing how to invert a binary tree.

Have you had to deal with crazy tech debt scenarios in the past? What did you do to solve them? Leave a comment down below and share your experience!

Did you find this article valuable?

Support Fernando Doglio by becoming a sponsor. Any amount is appreciated!