Skip to content
Gun.io
October 28, 2026 · 12 min read

Technical Debt: How Engineering Leaders Measure It and Decide What to Pay Down

Ask a claims platform team how long it will take to support a new state, and the answer tells you more about its technical debt than any code scan. If coverage rules for each state live in a dozen conditional branches spread across the intake service, the adjuster app and a nightly export job, the team cannot quote the work without first finding all of them. That search, repeated on every change, is the cost of the debt.

Technical debt is the extra effort every future change pays because of an earlier design or implementation decision. Measure it by the interest you pay (slower changes, repeated incidents, onboarding friction and risk exposure) rather than by how much code looks untidy, and pay down the debt that sits on paths you change often or where a failure is expensive. Debt in code nobody touches can usually wait. Debt in the code your roadmap runs through cannot.

What Is Technical Debt?

Technical debt is the gap between how a system is built and how it would need to be built to make today’s changes cheaply. When Ward Cunningham introduced the metaphor in 1992, he described shipping first-time code as going into debt and counted every minute spent on not-quite-right code as interest on that debt. The principal, by extension, is the work needed to fix the design. The useful part of the metaphor is the interest, because interest is what slows a team down and what a business can feel.

Some debt is deliberate. A team shipping a first version of a claims intake form may store the claim status as a free-text field because it has three statuses and a launch date. That was a reasonable trade. It becomes debt when reopened claims, partial payments and subrogation arrive and the text field cannot represent them without string matching scattered through the codebase.

Some debt arrives without anyone choosing it. Dependencies age, a PDF library falls out of support, a framework’s recommended patterns change, or the people who understood a module leave. And some code that looks like debt is not. A pricing module written in an old style, covered by tests and changed twice a year, may cost you almost nothing in interest. Rewriting it would spend principal you never needed to repay.

How Do You Measure Technical Debt?

Measure technical debt through its effects on the work, collected per area of the system rather than as one number for the whole codebase. The goal is to show where interest is being paid, how much, and on what kind of change.

SignalHow to observe itWhat it suggests
Change costFiles and services touched per change in one area; time from first commit to production for that areaLogic is duplicated or tightly coupled
Defect concentrationIncidents and bug reports grouped by moduleFragile code or missing tests on a busy path
Estimate spreadHow far estimates for one area miss compared with othersNobody fully understands that part of the system
Onboarding dragHow long a new engineer takes to make a safe change in an areaKnowledge lives in people, not in code or documentation
Risk exposureUnsupported runtimes, dependencies with known vulnerabilities, manual deploy stepsDebt that may not slow you today but can stop you suddenly

Two of these come straight from your existing tools. Version control shows how many files change together, and your issue tracker shows where defects cluster. The others need a short conversation with the engineers who work in each area, which is often where the most accurate picture comes from.

Static analysis tools help, with a caveat. They measure properties of code, such as complexity, duplication and rule violations, and some convert those into an estimated remediation effort. That estimate is the principal by the tool’s definition. It says nothing about interest, because the tool cannot know which code your roadmap will touch next quarter. A module full of warnings that nobody changes can score badly and cost little, while a clean-looking service with a hidden coupling to the billing export can be your most expensive debt.

For a claims platform, a useful measurement exercise might find that most production incidents trace back to the nightly export to the adjuster scheduling tool, that adding a new state touches the same handful of files every time, and that the document generation library has an open security advisory. Those three findings are the first entries in a debt register.

How Should You Prioritize Technical Debt?

Prioritize technical debt by combining two questions: how often the area changes (or will change, given the roadmap) and how expensive a failure there would be. Debt that scores high on both gets paid down first. Debt that scores low on both stays where it is.

Failure is expensiveFailure is cheap
Area changes oftenPay down now, as a planned initiativeClean up as you go, inside feature work
Area rarely changesContain it: tests, monitoring, isolationLeave it alone and record it

The coverage rules on the claims platform sit in the top left. The roadmap adds states every year, and a wrong coverage decision affects real policyholders. Consolidating those rules into one tested module earns its cost the next time a state is added. The internal admin screen used once a month by two people sits in the bottom right, however dated it looks.

The bottom left needs the most care. An old integration with a reinsurance partner may change once a year, but a silent failure there could misstate exposure for months. The right move is often to contain it: wrap it in tests that pin current behavior, add monitoring that alerts when output looks wrong, and put a boundary around it so new code does not depend on its internals. Containment costs far less than a rewrite and removes most of the risk.

Keep a short debt register rather than a long backlog. Each entry should name the area, the interest you have observed (with an example), the change or event that would make it urgent, and an owner. A register of fifteen specific entries is more useful to a leadership team than three hundred tickets tagged “tech debt.”

Should You Refactor or Rebuild?

Refactor when the system’s model of the domain is roughly right and the problem is structure. Rebuild, in pieces, when the model itself is wrong or the platform underneath it has reached the end of its supported life. The refactor vs rewrite decision rests on that question more than on how old or messy the code is.

The claims platform’s scattered coverage rules are a structure problem. The rules are correct; they are just in too many places. Extracting them into one module, behind tests that check each state’s current behavior, is a refactor. The free-text claim status is a model problem. No amount of tidying will let a text field represent a claim that has been reopened, partially paid and then sent to subrogation. That needs a new status model, a migration of existing records and changes to every consumer of the field.

Even when the answer is rebuild, rebuild incrementally. A full rewrite asks the business to accept a long period with few new features while the old system keeps changing underneath the new one, and the new system has to catch up with rules nobody wrote down. Replacing one capability at a time, routing traffic to the new path once it matches the old one and retiring the old path afterward keeps the system running and gives you evidence at each step.

A rebuild is more likely to be justified when several of these are true:

  • The runtime, framework or database is out of support and upgrading in place is not realistic.
  • The domain model cannot represent cases the business now handles routinely.
  • Changes in the area consistently require touching most of the codebase.
  • The team can no longer predict the effect of a change, even with tests.

If only one is true, a focused refactor usually costs less.

How Do You Fund Technical Debt Work?

Fund technical debt work through the roadmap, not around it. Debt paydown that competes with features as a separate line item tends to lose, because its value is described in engineering terms while features are described in business terms. Tie it to the outcome it enables and it competes on equal footing.

Three funding patterns work together. The first attaches paydown to the feature that needs it: “supporting the next state includes consolidating the coverage rules, which makes every state after it cheaper.” The second is a standing allowance inside normal delivery for cleaning up code engineers are already changing, so small debt never grows into large debt. The third is a discrete initiative with an exit condition, used for debt that no single feature will pay for, such as replacing an unsupported document library or moving the nightly export to an event-driven integration.

When you ask for that third kind of funding, describe the interest in units the business already tracks: incidents per quarter traced to the export, hours of adjuster time lost when it fails, the security advisory that remains open. Then say what will be true when the work is finished and how you will check. “The export runs on events, incidents from it stop, and the advisory is closed” is something a finance leader can approve. “Improve code quality” is not.

Funding also depends on who does the work. Paying down debt in a busy area usually needs someone who already knows it, which pulls that person off features. Sometimes the better answer is to fix the plan rather than add people, which is the argument behind our essay on knowing when more engineers are not the answer.

Why Is AI-Generated Code a New Source of Technical Debt?

AI-generated code creates debt when code arrives faster than anyone builds an understanding of it. The code may work, but if nobody on the team holds a clear model of why it is structured the way it is, every later change starts with reverse engineering. That is comprehension debt, and because generation is cheap it can build up faster than the team’s understanding does.

The pattern shows up in a few recognizable forms: near-duplicate functions generated for similar requests, each slightly different; data handling that suits a small test dataset and strains at production volume; security settings accepted from a suggestion without review; and prototypes that were meant to validate an idea but became the production system. Writing ordinary code is no longer the expensive part. Data modeling, failure handling, security boundaries and architecture still are, and those are where generated code needs the most human judgment.

One of our published briefs, on paying down the technical mortgage of a vibe-coded platform, describes this shift. A venture firm built its platform for funding game studios’ user acquisition as a fast prototype that stored data in local Parquet files and loaded datasets all at once. As data volumes grew, the engineer who took over the infrastructure pushed the cleanup of duplicate records from overlapping ad-network data down into the storage layer with ClickHouse, refactored the backend into a modular pipeline, and built a PostgreSQL-backed billing portal to keep approved spend as fixed historical records. A temporary dual-write was used to prove the new system matched the old results before cutover. The prototype did its job, and the debt it created was paid down deliberately once the business model had proven out.

Governance is the preventive side of this. Our essay on treating AI governance as an engineering discipline makes the point that controls should increase with consequence, which applies directly here: generated code that touches billing or permissions deserves more review than generated test fixtures.

How Gun.io Helps Teams Pay Down Technical Debt

Our starting point at Gun.io is which debt is costing you and what the roadmap needs next; only then do we decide who should do the work or under which model. When your team already knows which areas to fix and has a lead to direct the work, staff augmentation fits: our engineers join that effort and your team keeps day-to-day direction. When the debt still needs to be assessed, scoped and owned through to a finished result, scoped project delivery fits better, and we take on more of the planning and delivery ourselves.

The work this involves is familiar to us: legacy modernization, performance engineering, architecture and technical leadership, and moving AI-built prototypes into production. For an independent view of a codebase before an investment or acquisition, see our technical due diligence work, and our engineering solutions show the areas we cover.

Frequently Asked Questions

Is All Technical Debt Bad?

No, deliberate debt taken on with a known reason and a plan to revisit it is a normal engineering trade. Shipping a simpler design to learn whether customers want a feature is often the right call. Debt becomes a problem when nobody records it, the interest starts compounding on a busy path, or the people who knew why it exists have left.

Who Should Own Technical Debt Decisions?

The engineering leader accountable for the area should own the decision, with the product owner agreeing on timing. Engineers closest to the code know where the interest is paid, but the choice of when to pay it competes with features, so it needs someone who can weigh both and answer for the result.

How Do You Explain Technical Debt to Executives?

Explain it as a cost the business already pays, with a specific example. Instead of describing code quality, show that the last three state launches each took longer than the one before, or that a recurring export failure costs adjusters a set number of hours each time. Executives can weigh a recurring cost against a one-time fix.

Does Technical Debt Exist Outside the Code?

Yes, infrastructure, data and process all carry debt. Manually configured servers nobody can rebuild, a database schema that stores dates as text, a deployment that depends on one engineer’s laptop, and missing runbooks all slow changes and raise risk in the same way tangled code does. Measure and rank them with the same register.

Should You Pause Feature Work to Pay Down Debt?

Rarely as a blanket rule. A full feature freeze for cleanup is hard to justify and tends to end before the work is done. Pausing features in one area while its debt is paid down, with a clear exit condition, is easier to defend and keeps the rest of the roadmap moving.

How Do You Stop New Technical Debt From Building Up?

Make debt visible at the moment it is created. Ask for a short note in the pull request or decision record whenever a shortcut is taken on purpose, review generated code with the same standards as hand-written code, and give engineers room to clean up the code they are already changing.

Price the Interest Before You Pay the Principal

Technical debt is worth paying down when you can name the interest it charges and the change it is blocking. If you are deciding which debt to tackle first, or whether a refactor or a rebuild fits your system, talk to us about the system you’re paying interest on, where changes slow down today and who owns the areas in question.

Gun.io

Sign up for our newsletter to keep in touch!

This field is for validation purposes and should be left unchanged.

+1 (615) 541-8095

team@gun.io

© 2026 Gun.io