Understanding technical debt
In the creation of a web site, there are several groups of people who participate: product managers or marketing representatives who are responsible for defining functionality and design, user interface designers who create the actual visuals, and the developers who are responsible for implementing the final product. Of these groups, developers tend to get a reputation for being a bit touchy and grumpy for coming up with reasons why things can’t or shouldn’t be done. The reason why this happens is because the developer is, consciously or subconsciously, trying to manage the project’s technical debt.
Technical debt, or tech debt for short, is quite simply the amount of technical work remaining on a project. It’s something that is hard to quantify, typically existing in one or more developer minds at any given point in time. There’s the initial debt of hours or days to completion which is usually the estimate delivered to the manager. After that, every technical decision that’s made comes with some sort of tech debt.
Deadlines rarely align with the amount of time needed to complete work, and so technical compromises are made along the way. There’s a short-term tradeoff to get something working initially. The developer knows the lifetime of the solution and accepts that he or she will have to go back and create the longer-term solution later on. While those looking in from the outside might consider this to be sloppy engineering, it’s actually what allows products to be released on time. And also how tech debt accumulates.
Tech debt doesn’t show up on any product roadmap and so developers frequently try to address it as they’re working on other features. In some organizations, a savvy manager may be able to buy the developers some time pay down their tech debt, but that is the exception more than the rule. Those making business decisions typically don’t like giving time for paying tech debt because, in their mind, the work isn’t resulting in any new features. Why should they give you time to work on something when the end result isn’t a new feature?
In the worst case, tech debt can accumulate to the point where the web application is destined to fail. A classic tech debt issue is scalability. Initially, the goal is to get the web application up and running so that anyone can use it. Decisions are made to allow that to happen. But an app that can handle 100 users isn’t built the same way as an app to handle 1,000,000 users. In the back of the developers’ minds are a list of things that need to happen in order to scale out: hit the database less, implementing several layers of caching, reduce the size of responses, figure out a faster way to process orders, and so on.
Just like monetary debt, tech debt is best dealt with before it gets too large and overwhelming. Regularly tending to tech debt is a process I like to call code hygiene. If you don’t go to the dentist for ten years and then finally go, chances are you’ll be in for a nasty surprise by not practicing proper dental hygiene. Code hygiene is the same. Keeping on top of your tech debt means regularly going in and addressing what you can with the time available. Good code hygiene means regularly:
- Deleting unused code – I always say that any day you can delete multiple lines of code is a good day, and one where you earned your paycheck. Unused code shouldn’t be allowed to live in a codebase because, just like bacteria, all it needs is one opening to cause a big problem. If you suspect code isn’t being used, verify and then remove it. Don’t make a note to do it later, thus creating more tech debt, do it immediately. Less code means less to go wrong and faster builds and deployments.
- Refactor code – The time to refactor is as soon as you notice a problem. Don’t allow sloppy or bad code to remain in the code base. Code has a way of duplicating itself without warning. New developers come in looking for an example, find bad code, copy it, and now you have two pieces of bad code instead of one. That’s more tech debt. Make sure that all code you check in is worthy of being copied to prevent future tech debt. When you’re building off of existing code, make sure to include some time in your estimates for refactoring.
- Rewrite code – It’s rare for developers to be able to rewrite something from scratch, but it’s a necessary part of code hygiene. Good code should be able to run for five years without being rewritten; bad code needs to be rewritten as soon as possible. You should always try to refactor first, but if that fails, it’s time to rewrite. Making the business case for rewriting is difficult, but if you can tie the rewrite to a new feature, you have a better chance of getting the time.
Technical debt is a part of every project, and one that needs to be better understood by all parties involved. Building time into every release for code hygiene is a good idea and can take many forms: bug bashes, where everyone takes a day or two and just works on bugs, engineering-driven features, which are features of the platform rather than end-user features, and code reviews, where engineers inspect each other’s code, are all good practices to have on the team to ensure tech debt doesn’t get out of control.
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
Both comments and pings are currently closed.




7 Comments
You didn’t mention testing! “I’ll write tests later” is a huge IOU that you’ll probably regret later.
Jay Young on February 22nd, 2012 at 12:31 pm
Great post. I especially appreciate the observation that “code has a way of duplicating itself without warning.” It’s easy to get lazy and copy what’s already been done because developers think “it must be good if it’s in the repository already” (even if that belief doesn’t apply to their own code!) Tech debt not only needs to be prevented in the first place, but if it’s going to happen it needs to be identified early, commented-on extensively, and tracked relentlessly so no one makes the mistake of confusing it with good design.
Steve Carlson on February 22nd, 2012 at 2:20 pm
We’ve recently started referring to our tech debt as “quality debt” to better convey the urgency of our need to address it. We’ve seen a positive response so far but I’m concerned it will only last so long….
James Greene on February 22nd, 2012 at 3:08 pm
You mention good code should be able to run for five years without being rewritten. Is that a personal rule of thumb based on experience? Not that I disagree, just curious how you came up with that.
Richard Hansen on February 22nd, 2012 at 8:53 pm
@Jay – testing falls into the category of “things you put off”. So while not explicitly mentioned, it’s definitely something I keep in mind.
@James – I love that.
@Richard – Five years is based on my experience. Generally I find that people tend to rewrite their software from scratch about every five years. It usually takes about 18 months to build out a new project (not to “launch”, but to make the infrastructure into what you need it to be). You’ll easily spend the next 18 months maintaining that setup, and at that point, people tend to start thinking about how they’d rebuild it from scratch. However, they’re not able to make the business case for it for another year or two when the cracks start to show in the foundation. At the four or five year mark, that’s usually when there are new engineers who are no longer familiar with the original infrastructure and so they don’t know how to fix the problems that are arising. The solution: rewrite it!
Nicholas C. Zakas on February 23rd, 2012 at 12:49 pm
Nice post! A friend and I were just lamenting how often #1 is not practiced at our respective jobs, especially with regards to commented out code. Even some people who use and understand source control still commit huge sections of commented out code.
Shane on February 24th, 2012 at 7:30 am
“Making the business case for rewriting is difficult, but if you can tie the rewrite to a new feature, you have a better chance of getting the time.”
That’s what I see some developers doing actually, but I notice that it can be dangerous. If mistakes are made, as they usually are from typos, this can be problematic when errors surface.
I think a rewrite or new feature should be separated with a decent gap of testing. Don’t put all your eggs in one basket.
Nexii Malthus on March 6th, 2012 at 6:45 am
Comments are automatically closed after 14 days.