← Back to list

When I have time…

I have a game for anyone reading this. Write down how many times you’ve said each of these this week (or month), then estimate how much…

Mariandi Stylianou · 2026-06-16 07:10 · 1 claps · 6.0 min read
#refactoring #team-culture #developer-experience #technical-debt #productivity
Open on Medium ↗
Wiki topics: CUL · Culture & Media 💻 · Programming ⏱️ · Productivity 📚 · Books & Reading

When I have time…

I have a game for anyone reading this. Write down how many times you’ve said each of these this week (or month), then estimate how much time each one costs you:

  • When I have time, I need to fix this
  • It’s on my to-do list.
  • We should get around to doing this.
  • I will do this in a separate PR later.

It paints a picture of how we mentally clutter our work lives and stay in the clutter for (sometimes) ever, doesn’t it?

We have all been there. The team gets together and agrees on a new pattern, library or tool for good reasons. The team is either excited about the change or relieved. Everyone gets on board, PRs help reinforce the change, and eventually the new approach becomes normal. After a year, the team has made good progress, but the old version is still hanging around. Instead of speeding up, the team is maintaining both. Nobody can see the light at the end of the tunnel, and “I’ll get to it later” becomes a running joke.

This idea for this blog has been on my to-do list for 3 years, so I relate. So let’s discuss why this happens, different options and the trade-offs.

In a busy team, we always have to juggle a million priorities. We need to care about what we are building and why, ship it reliably, and keep it scalable. As a result, work on half-finished migrations and other cleanup often gets pushed aside, as it is often seen as time taken away from improving the product or reaching new audiences. Also, let’s be honest, not all half-finished migrations get in the way every day; some of them rear their ugly head occasionally (and probably at the worst timing ever). Some of it genuinely isn’t worth doing yet, so we weigh value against effort, against the cost of opportunity, and move on.

But what happens if we don’t ever work on these? We all know tech debt piles up regardless, but I would rather focus on the human side instead.

In every company I have been, teams start to get used to the workarounds and the impact on their productivity without noticing, 10 minutes here, half an hour there. But workarounds are the longer way to get there, so as the team scales, we collectively lose more time. I’ve noticed that developers tend to divide into those who will try to clean up the code as they go and those who will ignore it. And once the PR is out, the first group will give feedback to the second group to address before merging, because after all, we all agreed as a team to do this. Sometimes the feedback is accepted, sometimes it isn’t. Either way, time gets spent arguing about standards the team already agreed on, and we have spent more time discussing than it would take for the actual fix. Left unchecked, that friction over time turns into resentment and trust batteries get depleted. The list of steps keeps growing, which overwhelms people into giving up. And ownership starts to fade. Eventually, someone will ask whether rebuilding would be easier than fixing…

Let’s start with the reality that not all tech debt should be addressed, just like we don’t stop everything to fix a minor bug that happened once for one user. Some things are just not worth it, due to size, complexity, risk or just timing. We need to be brave and say it out loud, even if it doesn’t make us popular in that moment. The most experienced thing a developer can do is decide what not to fix, but we all fall into the wrong trap occasionally. Clearly defining to a team why a task is postponed or is off the backlog is necessary, as it sets the parameters (timing, effort or blockers) where we may need to reconsider down the line. By being transparent, I saw less resentment and gave a clear entry point for the conversation to reopen when the context changes.

Rebuilding a feature from scratch has the same appeal as any greenfield project: a chance to fix old compromises that didn’t work for us and start fresh. Done well, the team sheds lots of maintenance problems, users get a better UX, and the company has a great marketing opportunity. However, we need to be careful with big refactors. They attract the ‘while we’re at it’ crowd, and before you know it, a two-week job has a six-month roadmap. And you are just trading one set of compromises for another.

Refactors are powerful when paired with a review of the product itself, and deep-diving into which aspects of the feature are the most used, which our users just didn’t care for or get. My strong advice when planning a refactor is to avoid adding more bells and whistles, but to get back to what the feature was actually supposed to do and do it better. Asking any support team is the best way to find all of these! Refactors can also help reinvigorate team motivation and ownership, especially on inherited code.

What about work that isn’t big enough for a refactor project, or when we simply can’t afford it? Gradual improvements work, but they need discipline and can take a very long time. They need consistent advocacy to survive a couple of tough sprints or to not lose momentum near the end. Always leaving the code better than when you picked it up does wonders. We must focus on a few priorities to avoid the temptation to fix everything at once, which is a slow rabbit hole. Picking from the low-hanging fruit or attacking a big problem in smaller iterations are both reasonable options, and having the conversation helps set expectations, both for the code writers and reviewers and verbalises the exceptions. For instance, when introducing integration tests, asking everyone to add complete coverage for the files they are working on won’t work, as it’s too much effort, and they simply won’t want to do it. Selecting to add enough to cover their changes, and maybe one more, tends to work better. Nobody should expect better test coverage on hotfixes to production. That’s a follow-up ticket. What we need is a plan to build momentum and persistence.

Also, we should consider spending a bit of time on automations, as having a tool or a dashboard that will track the data really paints the picture where we are at, and can motivate people to push through the tail end. Finding tools or creating scripts that will address issues is also brilliant, as long as we don’t spend more time on these than on the actual work. Working on the timing is also important. When we are deprecating an old library, let the teams work on their roadmap using the new one first. Once there are only a few instances left, then a couple of tickets to remove the last instances will allow us to forget the old library’s existence. We saw this when moving from JS to TS (not a library, I know). New work used TypeScript by default, and small areas were migrated whenever we touched them. After a few years, most of the codebase had been converted. We finished the remainder by adding a migration ticket to the board each week for the areas where we didn’t have any plans until the work was done. It wasn’t fast, but it avoided swamping the roadmap.

Lastly, it wouldn’t be 2026 if there weren’t a section on AI here. Whilst the new shiny tool is taking everyone by storm, tons of opinions are starting to surface. One side argues that with AI producing a lot of the code, conventions, naming patterns, and other tech debt, related to human comprehension doesn’t matter anymore. The other side argues that AI is finally giving teams a chance to increase the quality without compromising on the velocity. Both sides have a point. Whilst AI may reduce the impact of some forms of tech debt on the team’s speed, it also makes cleanup cheaper than ever. More importantly, agents learn from the code around them. They’ll happily repeat your worst patterns without a second thought, and they won’t even have the decency to look embarrassed about it. Even if you set enough details in the .md files and your prompts, occasionally they can slip when the context compacts. Since AI has made it remarkably easy to scrape entire repos, why not use this as an excuse to do both? Audit which tech debt still gets in the way for both humans and agents, and then actually finish the cleanup, maybe in the background. Fewer ghosts in the codebase for everyone.

By focusing on less, we can achieve more, and we can clear a path to a nicer DX where debates on PRs are on the important aspects of the code, and not whether an agreed standard needs to be met. We can make decisions like refactoring or gradual improvements when each is the best choice, and not because we simply don’t have another choice.


메타데이터
post_id
fde00a39c7e0
slug
when-i-have-time-fde00a39c7e0
url
https://medium.com/@mariandi-stylianou/when-i-have-time-fde00a39c7e0
canonical_url
https://medium.com/@mariandi-stylianou/when-i-have-time-fde00a39c7e0
author_url
https://medium.com/@mariandi-stylianou
status
ok
fetched_at
2026-06-23 03:48:11