Make time to address low-hanging technical debt

Making the time to address smaller bits of tech debt has been great for several of our projects.

Over the last month, we’ve worked with two different clients to spend time tackling low-hanging technical debt. This isn’t done often enough in development teams. In this article I talk about what low-hanging technical debt is, why you should take time to pay it off, and how we went about it.

There are all sorts of technical debt that projects get themselves into over time. From pushing a small change without tests all the way to deploying to undocumented architecture.

There are even more ways to pay back technical debt, some more sustainable than others. One day I will write about some of my favourite practices to ensure you get into as little debt as possible, explain why debt is sometimes a great thing, and sustainable ways to pay it back. Today though, we’re talking about clearing off some low-hanging technical debt!

What is technical debt

Before I start talking about low-hanging technical debt, let me try and explain the concept of technical debt, so we’re all on the same page.

Imagine you’re building a house. Technical debt is like taking shortcuts or making quick fixes during the construction. Instead of using high-quality materials and following proper building techniques, you choose cheaper or easier options to save time or money.

At first, these shortcuts are convenient because they allow you to finish the house quickly. Yet, over time, these compromises can cause problems. The low-quality materials may wear out faster, the foundation may become unstable, or the electrical wiring may become tangled and hazardous.

In the world of website development, technical debt is similar. It occurs when developers take shortcuts or make temporary fixes to meet deadlines or cut costs. These shortcuts may work initially, but they can lead to issues later on. The code can become difficult to understand or maintain, bugs may start appearing, or the website may become slower and less efficient.

Like a house, the longer technical debt persists, the more costly and time-consuming it becomes to fix. It can slow down future development, introduce new bugs, and make it harder to add new features.

What is low-hanging technical debt

Low-hanging is a very subjective term, and it will vary between project and team. I think of it as something that easy to spot and easy to address.

If it isn’t easy to spot or isn’t easy to address, it could still be worth while fixing, but it falls out of scope for this article!

The best way to describe what I’m talking about is with some examples. These are real examples from real projects;

  • Images in the assets directory that are not referenced anywhere anymore
  • Loading dependencies in but not used anymore
  • CSS hanging around for a feature that got removed

These three examples are share similar traits;

  • Easy to verify
  • Easy to remove
  • Small improvement to some part of the development, deploy, or end-user experience

If I’ve explained things well enough, we should be on the same page about what low-hanging technical debt is.

Why should we care about this small stuff?

You might be asking why is it worth caring about removing a couple of images or some old CSS, especially when you know there are bigger issues to fix in the app.

I’m glad you asked!

There are loads of reasons why we should care about this smaller stuff, each of these could be an article in its own right.

Small numbers turn into big numbers over time

Let’s imagine you have some CSS for a form that no longer exists on the app. Someone removed the pages but they forgot to remove the CSS. This happens a surprisingly large amount of the time.

The CSS in question might only be a handful of bytes once compiled and compressed. But if you start to multiply out how many times a day those extra bytes are being sent, by how many days that CSS could sit there for, you start to get some pretty big numbers.

It doesn’t even matter which angle you are looking at the number from. Your hosting bill, your page weight, heck, even your compilation time at deploy. Over a big enough time scale this adds up.

Broken windows

To paraphrase the broken windows theory, visible signs of crime encourages more crime. So broken windows in a place lead people to assume it is okay to break more windows.

This theory has lead to some suspect policing decisions, but it holds well for website development.

If I’m working on a codebase where there are clear signs that no one cleans up after themselves, it will make it easier for me to cut corners and not clean up after myself.

The inverse is of course true. If there is a long history of people taking care to do the right thing, I will almost feel pressured into maintaining those practices.

Developer experience

Developers will come up with all sorts of user-hostile tool chains under the guise of developer experience, but those same developers will keep redundant files in their projects which makes searching for relevant code harder. I’ve never understood that.

Fewer “things” in a project, be that lines of code, dependencies, assets, etc. means the remaining stuff is easier to search and reason about.

Assets are an excellent example of this. If the images folder in your project is filled full of old versions of logos or pictures that you shouldn’t use anymore, you are unlikely to use that assets directory to find a good image to use, instead you will add a new image into it each time.

By removing things we don’t need, we make it easier to spot the things we could use or improve.

Zarro boogs

Bugzilla returns “Zarro Boogs” when there are no reported bugs in a project. This is a bit of a joke to mean that there is never “zero bugs”, only that you haven’t found all the bugs yet.

The only code I’ve ever experienced with zero bugs is deleted code.

Similar to what I talked about in developer experience, removing stuff, even stuff of little consequence, protects the project from it becoming an issue in the future.

I’d much rather debug an issue with dependency loading knowing that we use all loaded dependencies.

The endorphins of shipping

Let’s be honest, it is fun to ship stuff. Especially when the thing we are shipping is tightly scoped and final.

Removing some unused JavaScript is a concrete ticket, with no potential for iteration. Once that ticket is done, it is done.

Sometimes the team can get stuck on longer tasks that take longer to see the light of day, don’t underestimate how nice it feels to deliver very specific bits of value quickly.

How we address low-hanging technical debt

If you’re still reading then, hopefully, we’re on the same page about what low-hanging technical debt is and why addressing it is a good thing.

This next section is all about how we went about addressing some of the issues.

Teams come in all shapes and sizes, on one of the teams I’m a consultant helping out, and on the other we (tosbourn ltd) are the team.

Regardless of the makeup of the team, the goal should be to tackle things as quickly as possible. If it takes 5 days to pull together a plan to address this low-hanging technical debt, then it won’t see a good return on investment.

This is how we did it.

Do a project review

Take half an hour to look at different parts of the project, like dependencies or assets. Time boxing works because all we need to know is if it feels like there is something worth digging into a bit more.

For example, go into the assets directory and pick on a few images, search to see if you can see if the project uses those images. If you find an example where it looks like it isn’t, create a quick note or ticket to capture it.

Ditto with the dependencies. Have a quick review of the package.json or similar, and pick on a couple of dependencies that you don’t have personal knowledge of their use. You might find the project uses everything you sample, if so that is fine, but if not, again write a quick note.

The areas you investigate will vary depending on the project, and it doesn’t need to be a complete review, just enough to get a couple of notes to dig into.

Make the notes actionable

This next step will change depending on the makeup of the team. If you are “the team” then your notes might be enough and you can continue onto the next step. If someone else will be scheduling or performing the work, then you need to take the note and flesh it out to make it actionable.

The goal here is that the development work could be done by any developer on the team fairly quickly. For example, if you spotted that there are likely some images not being used in the project anymore, a ticket might read something like;

Review and tidy up images inside of /assets directory

On a quick review it appeared that we have images inside of /assets/images which aren’t referenced anywhere in the project. We should only store images that are actively being used, so this ticket is concerned with tidying up this directory.

An example of an image we found to not be referenced was /assets/images/logo-bw.png

Acceptance Criteria

  • Check to see if each image is being referenced
  • Remove any images that aren’t being referenced
  • Ensure project compile steps continue to work and tests pass

Remember, we are addressing low-hanging stuff here. If the review or the change required is a much larger refactoring. Try and break it down into something small and actionable.

For example, you might have reviewed the project README and spotted that there is no documentation to cover deploying one part of the app. It has never come up before because the knowledge is known internally by the people that do it.

Writing proper documentation could take days and will need to be maintained. Whilst this is something that would be worth spending the time on, for our case it would be enough to have an immediate ticket to say update the README with who to contact if you have questions about deploying this specific part of the app.

There will be some people that will wince upon reading that, and might argue that adding a small note to the README is wasted time when the ultimate goal is proper documentation.

I’ve worked on too many projects were the perfect state has got in the way of a better state. Tiny steps will always be more sustainable than giant leaps.

Do the work

In both projects recently we found that spending a dedicated day to work on things worked out well.

Whilst doing the work you will find other things to improve. That is the beauty of clearing away low-hanging tasks, you will find things that were hidden before. Be pragmatic in how you handle this.

Some things you can sneak into the ticket you committed to, if you found an unreferenced font file whilst looking at deleting unused images, that is very much in the spirit of the ticket, delete it at the same time.

For anything else, take a note or create a ticket.

Rinse and repeat

I don’t know if there is a project in existence that wouldn’t benefit from this type of review and quick tidy up.

There are plenty of projects where nothing will be found because things are well maintained as part of day-to-day development. For every project like that there are ten that think they are like that.

That said, you can’t spend all your time working on quick improvements. I’d suggest at least once a year, or more like once a quarter as a good time frame to consider doing this.

The actual cadence will depend on the project and the team, but if you time box both the review and doing the work, you will find you get lots of value from little effort.

Recent posts View all


The best way to test model scopes in Rails

Learn about Rails scopes and how to best test them with both Rspec and Minitest


Finding out what called a Ruby method

A quick way to understand what is calling your code using the caller method