Skip to content
Rotwise
Technical debt7 min read

The debt AI-generated code leaves behind, and where it hides

AI assistants front-load speed and back-load risk. A tour of the eight kinds of debt we find in generated codebases, and how to score what actually matters.

The first month with an AI coding assistant feels like cheating. Features that used to take a week take an afternoon. The backlog shrinks. Then, somewhere around month four, the codebase starts to feel like it was written by a stranger, because in a sense it was.

This is not an argument against the tools. It is a map of what they leave behind, so you can find it before your users do.

Why AI debt is different

Human technical debt is usually a known shortcut: someone chose speed, knew the cost, and meant to come back. AI-generated debt is different in three ways.

  • There is no shared mental model. Nobody on the team remembers writing the code, so nobody remembers its assumptions.
  • Consistency drifts. Each prompt is a fresh start, which is how a project ends up with three date-formatting helpers and two HTTP clients that disagree about retries.
  • Confidence without context. The output looks finished. It is formatted, commented and plausible, which makes it much easier to merge without reading.

The eight places it hides

When Rotwise scans a repository it sorts everything it finds into eight categories. They are a useful checklist even if you never run a scan.

  • Security. Hardcoded secrets, SQL built from string interpolation, mass assignment without a permit list, endpoints that forgot to require authentication, wide-open CORS. This is where the P0 findings live.
  • Correctness. Swallowed exceptions, missing error handling around I/O, payment endpoints with no idempotency key, counters incremented without a lock.
  • Performance. N+1 queries, whole tables loaded into memory, synchronous HTTP calls inside a request, foreign keys without indexes.
  • Duplication. The same utility written four times with four names, copy-pasted API clients, a utils file in every directory.
  • Dead code. Unused exports, unreachable branches, forty lines of commented-out code that "might be needed".
  • Missing tests. Files with no test at all, public behaviour with nothing pinning it down.
  • Maintainability. God methods, cyclomatic complexity in the forties, TODOs that outlived the person who wrote them.
  • Configuration and operations. Environments that differ silently, migrations nobody references, secrets that live in three places.

Score what matters

A count of findings is not a score. Two hundred low-severity smells matter less than one live key in a public repository, and a raw number hides that. A useful debt score weights every finding by severity and by how confident the analysis is, normalizes for the size of the codebase, and drops anything a second pass could not confirm.

Then it tracks the number over time. A codebase at 62 that was at 71 last month is a healthy codebase. A codebase at 40 that was at 20 is a fire, whatever the absolute number says.

What to do this week

  • Run a baseline. You cannot pay down what you have not measured.
  • Fix the P0s first, this week, before anything else.
  • For any file you are about to change that has no tests, write characterization tests before you touch behaviour.
  • Schedule the rest in small batches, one pull request at a time, and keep shipping features in between.

The tools that got you here are not the problem. Treating their output as finished is. Keep the ambition. Lose the tech debt.

← All posts