AI-generated technical debt: research and how to catch it

Five studies on how AI-written code piles up debt, the git-history signals that reveal it, and a 433-line method fixed in under three hours.

Codebase By The YATFA team
On this page

Short answer: AI-generated technical debt is the structural cost that builds up when code from AI assistants and agents is accepted one change at a time and nobody restructures it. It looks like duplicated blocks instead of reuse, methods that grow with every feature, and complexity that no single review catches. Studies of thousands of repositories show that it is real and measurable: complexity and static-analysis warnings rise after teams adopt AI tools, and they stay up after the speed gains fade. The answer is not to stop using AI. Watch the trend in your git history, refactor the hotspots behind tests, and make that work routine instead of heroic.

Research on AI-assisted development and code structure: complexity, duplication, code smells and the cost of low-quality code

Four findings on what AI-assisted development does to the structure of code. Each study is linked in the sections below.

What is AI-generated technical debt?

Ward Cunningham introduced the technical-debt metaphor in his 1992 OOPSLA experience report. Shipping code that reflects an incomplete understanding is like borrowing: it speeds you up today, and every later change to that code pays interest until the code is rewritten. Martin Fowler later sorted debt into a quadrant: it is either deliberate or inadvertent, and either prudent or reckless.

Most AI-generated debt sits in the inadvertent half. Nobody decides to duplicate a helper or to let a method pass 400 lines. The assistant writes a working change where it was asked to, the diff looks reasonable, and the structure gets worse one acceptable step at a time.

Reckless Prudent
Deliberate "No time to design — ship whatever the assistant produced." "Ship now, schedule the cleanup — and then actually do it."
Inadvertent Generated code is merged without anyone noticing that it duplicates an existing helper. After a dozen AI-written features, the team realises the module needed a different shape.

What does the research say about AI and code quality?

The research is newer than the tools, but it points the same way. AI makes producing code faster, and the structure of that code degrades unless someone looks after it.

Study What was measured Finding
He et al., MSR 2026 806 GitHub projects that adopted Cursor, compared with 1,380 matched projects that did not Lines added jumped 281% in the first month, and the speed gains faded after two months. Static-analysis warnings rose 30% and code complexity 42%, and both stayed up. Higher warnings and complexity predicted later slowdowns
GitClear, 2025 211 million changed lines, 2020–2024 Copy/pasted lines grew from 8.3% to 12.3% of changes. "Moved" lines, the signature of refactoring, fell from 25% to under 10%, and in 2024 copy/paste outnumbered moved code for the first time
Sonar, 2025 Static analysis of code written by leading models, including GPT-5, Claude Sonnet 4 and Llama 3.2 Code smells, which are maintainability problems rather than bugs, made up over 90% of all issues found. Newer models did not reliably write cleaner code
OX Security, 2025 300 open-source repositories, 50 of them wholly or partly AI-generated AI code was not more vulnerable line for line. It showed ten recurring anti-patterns, such as excessive comments in 90–100% of repositories and a drift back to monolithic designs in 40–50%, and it reached production with less review
DORA, 2024 Survey-based model of software delivery performance Each 25% increase in AI adoption went with 3.4% better code quality and 7.5% better documentation. It also went with an estimated 1.5% drop in delivery throughput and a 7.2% drop in delivery stability

Why the structure matters: in Code Red, Adam Tornhill and Markus Borg studied 39 proprietary codebases. Low-quality code had 15 times more defects than high-quality code. Resolving an issue in it took 124% longer on average, and the maximum cycle times were nine times longer. Debt is not an aesthetic problem. It is where the bugs and the delays live.

Two caveats keep this honest. The Cursor study looked at open-source projects, which may not behave like a product team with a review process. GitClear, Sonar and OX Security sell tools that measure exactly what they report. The direction is consistent across all of them, though, and the effect is large enough to plan for.

Why does AI-written code pile up debt faster?

None of the mechanisms is new. AI just runs them at a higher volume than teams are used to.

Mechanism What happens Where it shows up
Changes land where they were asked for The agent extends the method it was pointed at, rather than asking whether the method should exist Files that only grow; methods far longer than the rest of the codebase
Generating is cheaper than finding Writing a new helper takes less effort than discovering the one that already exists Duplicated blocks; the GitClear copy/paste trend
Volume outruns review More code arrives each week than reviewers can absorb in depth Lower delivery stability (DORA); less-reviewed code in production (OX)
Each diff is fine on its own Debt is a trend across changes, and a review of one pull request cannot see a trend No review comment ever flags it
Nobody asks for refactoring Assistants respond to requests, and refactors are rarely requested Falling share of moved code (GitClear)

Which signals in git history reveal it?

AI-generated debt is easier to see in history than in any single change, because history shows the trend. The signals below need nothing more exotic than a git log and a static-analysis tool.

Signal How to measure it What it tells you
Monotonic growth Line count of a file at every commit that touched it, and how many of those commits were refactors A file that grew with every feature and never shrank is accreting
Long methods, against your own baseline Method length in non-comment lines, compared with your repository's 90th and 99th percentile Outliers are where accretion concentrated
Duplication in new code Share of duplicated lines or blocks in recent changes Reuse is failing; helpers are being re-invented
Hotspots How often a file changes, combined with how healthy its code is Debt that actually costs you, because people keep working there
Warning and complexity trend Static-analysis warnings and complexity per module, month by month The signal the Cursor study measured
Rework Code rewritten or deleted soon after it was written (GitClear calls it churn) Changes that did not fit the design
Review friction by area Time to merge and returned reviews per directory Where the structure slows everyone down

Hotspots deserve the most attention. CodeScene's hotspot documentation shows an example in which prioritised hotspots made up 1.2% of the code but drew 12.5% of the development effort and 45% of the detected bugs. Your numbers will differ. The shape — a small part of the code taking a large share of the pain — is typical.

What are the best practices for managing AI-generated technical debt?

1. Measure the trend, not a snapshot

A single code-quality score tells you little. Track complexity, warnings and duplication per module over months, and mark the date your team adopted each AI tool. A rising line after adoption is the early warning the Cursor study describes.

2. Read git history for accretion

Once a month, list the files whose line count only went up and the commits that touched them. A file that took seven feature commits and no refactoring commit is a candidate, whatever its absolute size.

3. Rank against your own codebase

Universal limits such as "methods under 50 lines" fit some codebases and not others. Compute your repository's own distribution and flag what sits far above its 99th percentile. Count non-comment lines, so that a well-documented method is not mistaken for a complex one.

4. Fix hotspots first

Debt in code nobody touches costs almost nothing. Debt in a file that changes every week costs every week. Cross the accretion list with change frequency and start where they overlap.

5. Make refactoring its own change

Fowler defines refactoring as changing the internal structure of code without changing what it does. Keep it that way in practice: a refactor ships as a separate change, never mixed with a feature, and its acceptance bar is "the existing tests pass without being edited". If no tests pin the behaviour, write them first, and then refactor.

6. Hold new code to the bar

Sonar's approach, described in its documentation on new code, applies the quality gate to code added or changed recently instead of to the whole legacy codebase. For AI-assisted teams that is the cheapest control there is: duplication and complexity are stopped at the door, before they become history.

7. Refactor continuously, not in a big rewrite

Fowler's opportunistic refactoring — improving code whenever you work in it — beats a quarterly clean-up sprint that never gets scheduled. With agents, "whenever you work in it" can mean a standing check that runs after every few features.

8. Ask every refactoring proposal for evidence

"Clean up the upload code" is not a ticket. A good proposal says what was found (with numbers from history), why it matters now, how the change will be shaped, and how you will know it is done. That keeps refactors small and reviewable, and it makes them easy to approve or reject.

9. Let agents do the mechanical part, under rules

Extracting a validator, splitting a method or removing duplication is work AI agents do well when tests pin the behaviour. Decide in advance which refactors may go ahead without a person, such as those that are behaviour-preserving and fully tested, and which always wait for review.

A real case: one method that grew from 179 to 1,062 lines in six days

The example comes from YATFA's own codebase in September 2026. An upload endpoint for producing demo videos was built in seven feature slices over six days. Each slice was its own ticket and its own commit, and each was reasonable on its own. Together they produced the largest method in the application.

How one controller file grew across seven feature commits, and what the refactor did to it

The file's size at each commit that touched it: seven features, no refactoring, then the extraction.

An agent reading the git history, without being asked, found the pattern and measured it.

What the history check found Value
Commits that touched the file 7, all features, none a refactor
File size 179 → 1,062 lines in six days
Longest method 433 lines, the largest in the application; the repository's 99th percentile is 42
What the method was A chain of upload checks, each an early return with a named error: 27 in the first count, 33 once the whole chain was re-measured
Safety net 87 tests that pin each refusal message and check that a refused upload creates nothing

The refactoring proposal: what was found in git history, why it matters and how the change is verified

The proposal carried its evidence: the history, the measurement and the tests that would prove nothing changed.

From the proposal to the merge took two and a half hours on 17 September 2026 (times in UTC).

Time Step
06:13 Proposal filed with the git-history evidence
06:52 Proposal approved under the project's autonomy settings
07:00 Ticket written; every figure re-checked on main, and the check count corrected from 27 to 33
07:18 Work started
07:35 Change submitted for review
07:53 Review passed
08:23 QA passed
08:47 Merged

The controller went from 1,062 to 434 lines. The 33 checks moved into a dedicated validator, and the action now reads as authorise, validate, save, respond. All 87 tests passed without a single edit to the test file, which was the acceptance bar set in the proposal.

The lesson is not that any single change was bad. Each of the seven diffs was reasonable when read on its own. The debt was invisible in every pull request and obvious in the history, which is why the check has to run across history and not only inside a review.

Which tools help find and fix technical debt?

No single tool covers detection, prioritisation and the fix. This is a partial list of what teams combine.

Tool Type What it does
SonarQube Static analysis Rules for bugs, vulnerabilities and code smells, with quality gates applied to new code
CodeScene Behavioural code analysis Combines code health with change frequency from git to rank hotspots
GitClear Code-change analytics Classifies changed lines as added, moved, copy/pasted or churned, to show refactoring and duplication trends
Qlty Code quality platform Linting, duplication and complexity checks and coverage across many languages, in CI and code review
OpenRewrite Automated refactoring Deterministic recipes that apply large refactorings and migrations across a codebase
AI coding assistants Code generation Carry out a refactoring well when asked and when tests pin the behaviour — but someone has to ask
YATFA Agents that find work Reads code and git history for refactors like the one above and files them as proposals with evidence; your autonomy settings decide which go ahead on their own

How do you set this up for your team?

Step What to do Done when
1. Baseline Record complexity, warnings and duplication per module You have this month's numbers to compare against
2. Gate new code Turn on a quality gate for new and changed code Duplication and new issues are stopped before merge
3. Read history monthly List files that only grew, and methods above your 99th percentile You have a short candidate list with numbers
4. Pick hotspots Keep the candidates that also change often Three or four targets, not thirty
5. File each refactor on its own Evidence, shape and test bar in the ticket Each refactor is one reviewable change
6. Decide who approves Behaviour-preserving refactors behind full tests can go ahead; larger ones wait for a person The rule is written down, not decided ad hoc
7. Review and test it An independent review and a check that behaviour did not change The existing tests pass unedited

Steps 3 to 5 are the ones teams skip, because nobody owns them. In YATFA, agents read the code and its git history between your requests and file what they find as proposals with reasons. Your autonomy settings decide which kinds go ahead without you, and every change still passes an independent code review and QA. For the review side of the same problem, see how to review AI-generated code.

Frequently asked questions

Is AI-generated code worse than code written by people?

Not line for line, at least on security: OX Security found AI-written code no more vulnerable per line than human code. The difference is in volume and oversight. More code arrives, less of it is reviewed in depth, and the structural problems — duplication, long methods, complexity — accumulate faster than teams notice.

Can AI fix the technical debt it creates?

Yes, for mechanical refactoring: extracting a method, splitting a class, removing duplication. It works when tests pin the behaviour and the change is reviewed as a refactor, as in the case above. What AI does not do by default is notice that the refactor is needed. That has to come from a check on history or from a person.

How do you measure technical debt in a codebase?

There is no single number. Combine structural measures (complexity, method length, duplication, static-analysis issues) with history (how files grow, how often they change, how often changes are reworked). Track them as trends per module, not as one score.

Should teams slow down their use of AI coding tools?

The research does not say so. DORA found AI adoption improved documentation and code quality while hurting delivery stability. That pattern suggests adding controls such as small changes, independent review, refactoring and quality gates, rather than removing the tools.

What is the difference between technical debt and bugs?

A bug is behaviour that is wrong today. Technical debt is structure that makes tomorrow's changes slower and riskier. Sonar's analysis found that over 90% of the issues in LLM-written code were code smells, which is debt rather than bugs, and the Code Red study shows that this debt is where future bugs concentrate.


YATFA builds an engineering organization around AI coding agents: work found in your codebase, review by an agent that didn't write the change, QA with proof, and knowledge that stays current. See how YATFA finds refactors in your git history, or start free.

Keep reading

Put it to work on your own codebase