Skipped Refactoring Is a Loan Your Team Never Booked

Picture a team's velocity chart. It has never looked better. Their roadmap is on track, and the stakeholders are happy. That's quite a combination, and most of you have seen a dashboard like this one.

Then I looked underneath it, which is what I usually like to do. In the last six weeks, this team merged exactly one commit that moved or consolidated existing code. One refactor in six weeks. Over that same stretch, their copy-and-paste doubled.

So my question is a simple one. Is that team fast, or is that team borrowing?

The core idea
Refactoring is debt service. Every shortcut a team ships is a loan, and a loan nobody writes down still charges interest. You just can't see the rate.

What the dashboard gets right

I want to start with what that team is doing well, because I don't think the dashboard is wrong. We love empirical data. They are shipping. Features are landing in front of customers, that's real, and it's one of our primary outcome goals in agile.

I'll take speed all day long. I'm happy, but I'm never truly satisfied. I just want to know what the speed costs, because there are almost always trade-offs involved, and most of the time they're hidden.

Velocity only books one side of the balance sheet

Last week we talked about counterweight measures, and I want to put that idea into practice here. Think about this like a finance person would. A balance sheet has assets and liabilities, and you need both to know where you stand. You can't look at one side and call it a picture of the business.

Every feature you ship is an asset. You can demo it. You can put it in the release notes and talk about it in a sprint review. You've checked a lot of the boxes of working iteratively and incrementally, and like any good asset, it should bring in cash flow.

Every shortcut that shipped with it is a liability. The duplicated function. The helper nobody consolidated. The module that got a little harder to change for the next person. Those liabilities helped produce the velocity, because cutting corners is faster, but they never show up on the velocity chart as technical debt. They don't show up much of anywhere. They become hidden waste that's easy to glaze over, and I rarely see a team write any of those shortcuts down.

Maintainability is the balance sheet. A team that only watches velocity is only booking the assets. It's reading the P&L without looking at the debt it took on to earn the profit.

Here's how I put it. You can generate your way to this quarter's roadmap. You can also refactor your way to next year's roadmap. Only one of those is usually on the calendar, and we all know which one.

What the data says about refactoring in the AI era

I'm a data guy, and one team is just a story. So I went looking for data that could test my hypothesis.

In June of this year, GitClear published a report called The Maintainability Gap. It looks at 623 million code changes from 2023 to 2026. Those changes come from GitClear's own customers and from corporate open-source repositories, so this is a vendor's data about its own customers, not a sample of the whole industry. The report was sponsored by GitClear and GitKraken, and both offer tools to measure what it measures. I still think it's good enough to look for signals.

Refactoring is down 70%

The measure I care about most is what GitClear calls moved code: the share of changed lines that relocate or consolidate existing code. Think of it as their signal for refactoring. If you pull duplicated logic into one place, it shows up as moved code.

In 2023, moved code was 12.7% of changed lines. In 2026, year to date, it's 3.8%. That's a 70% drop. "Year to date" here means the first five months of the year, so 2026 is an early read.

Copy-paste and duplication are climbing

Now look at the other side. GitClear counts lines as copy-pasted when they're repeated within a single commit. Over the same window, copy-pasted lines went from 11.1% of changed lines in 2023 to 15.7% in 2026, up 41%.

Duplicated code blocks, meaning five or more repeated lines in a row, rose 81% from 2023 to 2026 year to date. GitClear says that's the highest level it has recorded.

Refactoring goes down. Copying goes up. Duplicated blocks go up.

What this data can and can't prove

To me, this shows a direction. It doesn't prove a cause. I'm not trying to be pedantic, but the sample grew a lot over those years, so the mix of teams in it changed a lot too. The data has a hard time separating one cause from all the others.

Does that make it useless? Absolutely not. A direction is enough to make you go look at your own team, and we're professionals. We can do some deductive reasoning.

Why AI makes skipping the refactor feel free

Generating a new function takes seconds now. Finding one that already exists, understanding it, and folding your need into it takes thought. It's much harder, and that's the messy part of sharing a code base.

When one of those options is nearly free, we all know which one wins, because developers are always under pressure. The cheaper generation gets, the more optional refactoring starts to feel. And it isn't optional.

I hear leaders talk about refactoring as cleanup all the time. Nice to have. Something we'll get to when things slow down. Things don't slow down. You know that and I know that. So we need to coach teams, and the leaders around them, to manage this responsibly.

Refactoring is debt service

So I'd say it differently: refactoring is debt service. Most business leaders understand debt, and the technical debt metaphor has been around a long time.

Where the technical debt metaphor came from

We can credit it to Ward Cunningham. I use his video in my classes a lot. In a short 1992 experience report about the WyCash portfolio management system, he wrote that shipping first-time code is like going into debt. He described every minute spent on not-quite-right code as interest on that debt. He also wrote that a little debt can speed up development, as long as it's paid back promptly.

I agree with him. There will be times when we make an intentional decision to cut a corner and get something out there. That's a reasonable business call.

A loan you didn't book still charges interest

What worries me is a different kind of debt: the debt nobody writes down, so nobody pays it back on purpose. This part is my extension of Cunningham's metaphor, and it's what I teach my clients.

A loan you didn't book still charges interest. Somebody is paying for it somewhere. You just can't see the rate.

It also hits your credit score, and in our world that credit score is credibility. If you're always slow because you aren't refactoring, you can't turn around and ask for more refactoring time, because people no longer trust you. It's a recursive problem.

When your team refactors, it's making a payment. When it skips the refactor, the balance and the interest grow. The interest doesn't arrive as a line item, though. It arrives as every change taking a little longer, with a little more friction than before. You know the friction is there, but it's hard to see or put a number on. If we could show it to business leaders as a line item on a ledger, they'd focus on it right away, because it's probably a bigger number than any of us would like to admit.

How one helper function turns into the same bug twice

Here's a deeper example for those of you who code or lead developers.

A team needs a small helper function. Something simple, like formatting a customer's billing date. Somebody, or something, writes that helper inside the checkout service.

Next sprint, someone working on the notification service needs the same thing. Generating a fresh copy takes seconds. Finding the original and moving it somewhere shared takes a conversation, and more than that, it takes people converging on a decision together. That feels like a lot more effort and a lot more time, so they create their own. Later, another copy shows up somewhere else.

Each copy is a little different, because each was written fresh for the part of the system it serves. Everything works. As far as the customer knows, there's no problem. Velocity looks great. No harm, no foul.

Then a customer in a different time zone gets billed on the wrong day. They call in and complain. Someone finds the bug in the checkout copy, fixes it, and closes the ticket. Good work, thank you, off we go.

Three sprints later, an invoice email goes out with the same wrong date. Same bug, different copy. Nobody remembered the other copies existed, and why would they? Most of the people involved weren't part of those earlier conversations, and nobody had written the copies down.

That second bug is interest on a loan the team never knew it took out, and it affects the other teams and, worse, the whole organization.

What the payment would have cost

Look at how small the payment would have been, even though it doesn't feel that way in the moment. Roll the tape back. Move the helper to one shared home, point everything that needs it there, and delete the copies.

Most people would call that sound architecture and ask why we didn't do it that way in the first place. In the real world, it usually doesn't happen. And that consolidation is exactly the kind of change GitClear's moved-code measure is built to count, the same measure that fell 70% in their data.

I'm not saying every copy is a bug waiting to happen. I am saying every copy is a decision. When nobody writes the copies down, or better yet gets a second person to agree with the decision, nobody is really making that decision on purpose. It's left to one developer, in a code base that everybody shares.

"We already paid for that code"

I can hear the objection already, because I hear it from business leaders all the time. To most stakeholders, refactoring sounds like rework. We already paid for that code. It's working. Why would we pay for it again?

I understand where that comes from. No leader wants to fund the same work twice, so we should stop describing it that way. Refactoring is a strange word to most business leaders, and it doesn't mean redoing the feature. The feature still does exactly what it did. Customer behavior doesn't change.

Refactoring is part of what it costs to build fast in work that's irreducibly uncertain. We won't know something truly works until customers are using it. "It works on my machine" or "it works in the integration environment" isn't the same thing. Leaders resist funding refactoring because it looks like rework, and rework sounds like waste, when the work is actually there to prevent waste. Back to that recursive problem.

Leadership cue
Stop funding 100% of your team's capacity on new features. Give engineering and maintenance its own visible line in every planning conversation, so the debt gets paid on purpose instead of squeezed out quietly.

Plan your team's capacity in four lines

This is why I teach every team I work with to plan its capacity in four lines. Whether it's a quarterly roadmap session or a larger planning process, the team's capacity gets spent across:

  • Roadmap items, which are the new features.
  • Minor enhancements, responding to things we've already built, plus quick wins.
  • Defects, because you'll always have some.
  • Engineering and maintenance, where redesign, refactoring, and upkeep live. Think of it as the maintenance manual for the product.

The point isn't a magic percentage. The point is that nobody plans all of the team's capacity on new features. Once the maintenance line is visible, stakeholders get used to seeing it, and it gets funded on purpose. When it isn't visible, it gets squeezed, or quietly doesn't happen at all, and that brings its own complications.

You have to adult. You have to make trade-offs. It can't be new feature, new feature, new feature.

I'm not the only one saying to budget for this, by the way. GitClear's own first recommendation in the report is to budget for refactoring and legacy maintenance as first-class work. I've been saying that for about 18 years. We just have a hard time looking at it.

Everyday refactoring vs. larger redesigns

That doesn't mean every refactor needs its own line item. Think minimum viable process, minimum viable bureaucracy.

The everyday kind should happen inside new work, in tens of minutes. I call it radical refactoring: the discipline and rigor to improve whatever you touch while you're building a feature. Ron Jeffries makes the case for this kind of incremental refactoring in his post on why refactoring doesn't belong on the backlog. You're already in the code and you're already testing it, so you're at liberty to change it. You leave it a little better than you found it. Do that consistently and, eventually, your whole system gets touched, and nobody needs to approve it. It's just how the work gets done. Some people will call that gold plating. It isn't.

The larger redesigns are different. Sometimes you get into a part of the system and realize it's simply junk. Those go on the backlog as their own redesign items, get ordered through real conversation and collaboration, and get booked against that engineering and maintenance line.

Keep the books with the Refactoring Ledger

What can you do next week, beyond putting those four lines into your planning process? I put together a simple tool called the Refactoring Ledger, and we're publishing it on our blog this Wednesday.

It helps a team estimate the maintainability debt a sprint may have added: the duplication that came in and the refactoring that got skipped. The goal is to keep that debt in front of you, so you can see it and make a decision about it. Then it helps you decide what to book next. Is it a redesign item for the backlog, or a working agreement for everyday refactoring?

It runs on what your team can already see in its own pull requests and its own backlog. You don't need a code analytics product to use it. Run it on your last sprint, just one, and see what you would have booked if anybody had been keeping the books.

So, is that team fast?

Let's go back to the team we started with. Six weeks without a refactor. Copy-and-paste doubled. A velocity chart that has never looked better. The stakeholders are happy because they don't know what they don't know.

Is that team fast? On the chart, sure. On the books, they're borrowing, and nobody wrote down the rate.

Speed you don't refactor isn't throughput. It's a loan with a hidden rate, and somebody is going to pay it. So go help your teams build the habit of refactoring as they go. It's how they take their throughput back, and it gives your chefs a clean, working kitchen to cook in. That's probably the better analogy for your business leaders anyway.

If you want your teams and leaders practicing this kind of planning, or you want help making maintenance visible in your roadmap, take a look at our upcoming classes. You can also get each week's topic, plus new tools like the Refactoring Ledger, in the Big Agile newsletter.

Happy refactoring.