Generated code is maintainable. Unread code is not.
The claim that AI writes unmaintainable code confuses a property of an artefact with a relationship between an artefact and a reader. Maintainability was never in the file.
The complaint arrives in a predictable form. Someone opens a pull request produced by an agent, reads forty lines, and says: this is unmaintainable. Then they list what is wrong with it, and the list is usually about style, or about a helper that duplicates one three directories away, or about a level of abstraction they would not have chosen.
I think the complaint is pointing at something real and naming it wrongly, and the wrong name leads to the wrong fix.
My position: maintainability is not a property of a file. It is a relationship between a file and the people who will have to change it. Generated code scores well on nearly every intrinsic measure we have ever used for maintainability. What it lacks is a reader, and no amount of improving the artefact supplies one.
Define the thing operationally
Ask what maintainable means and you get adjectives: clean, readable, well structured, idiomatic. None of those is measurable, which is why the argument never resolves.
The operational definition is: the expected cost of the next correct change. Cost in time, and correct meaning it does what was intended and does not break something else. That definition is useful because it forces you to name a change and a person. There is no such thing as maintainable in the abstract, only maintainable by this team, for the kinds of change this system actually receives.
Run generated code through that definition and the picture inverts. It is usually consistently formatted, conventionally structured, shallowly nested, comprehensively tested against the obvious cases, and free of the personality quirks that make a particular human’s code hard to follow. Judged against the median of what people commit at 6pm on a Thursday before a release, it holds up well.
What it does not have is anybody who was there when it was written.
Intrinsic measures, where generated code does well
- Formatting consistency
- Function length and nesting depth
- Naming convention adherence
- Presence of tests
- Comment density
Relational measures, where it does badly
- Someone can explain why it is shaped this way
- Someone knows what it must not do
- The alternatives considered are recoverable
- Its assumptions match the rest of the system
- A named person would notice if it changed
The one genuine intrinsic defect
I do not want to be glib about this, because there is a real artefact-level problem and it deserves its own name.
Context blindness is the failure where an agent’s output is internally coherent and incompatible with the repository. It calls an API that does not exist, or existed in a previous version, or exists under a different name. It reimplements a utility that is already there. It violates a local convention that is enforced socially rather than mechanically, because the convention lives in a reviewer’s head and not in a linter.
That is a genuine defect in the file. It is not about readers. And it is the one thing on the list that gets worse rather than better as the agent gets more fluent, because fluent wrong code passes the skim that would have caught clumsy wrong code.
But notice what fixing it requires. Not better prose style. It requires the conventions to exist somewhere machine-readable, and the existing utilities to be discoverable, and the deprecated APIs to be removed rather than commented as deprecated. Those are repository-level investments, not code-quality investments, and they are the actual work.
Why the wrong diagnosis leads somewhere expensive
If you believe generated code is intrinsically unmaintainable, the obvious response is to improve the artefact. Tighten the linter. Add a style gate. Point a second model at the diff and ask it to raise the quality. Buy a tool that scores the codebase and refactors the low-scoring parts.
Every one of those spends real budget improving the column where you were already fine, and none of them changes whether anyone has read the code.
Worse, the last one is actively counterproductive. Refactoring a region nobody understands, using agents nobody is closely reviewing, produces a larger quantity of unread code sitting on top of the unread code, and it produces a report saying the score went up.
The correct response to “nobody has read this” is narrow and boring: read some of it, on purpose, in proportion to what it would cost to be wrong, and keep a record of decisions so the record can do the work memory used to do.
What this means for how you spend
Three practical consequences, in order of how much money they save.
Stop paying for artefact quality you already have. If your generated code passes your linter, your formatter and your review checklist, additional spend on artefact scoring buys you a number, not a reduction in the cost of the next correct change.
Spend on making conventions mechanical. Every rule that lives only in a senior engineer’s review comments is a rule an agent will violate forever. Moving it into a lint rule, a type, or a failing test converts a recurring human cost into a one-off engineering cost, and it is the single highest-leverage thing available in this area.
Spend on recoverable intent. A chain from a line to the change, the criteria and the approver is worth more than any static score, because it answers the question that actually blocks the next change: why is this like this, and what was it allowed to do.
Where this breaks down
Fluent wrong code is a harder review problem, and I have underplayed it. My argument treats artefact quality as basically solved for generated code, but polish makes errors less visible. A subtly wrong assumption about ordering or nullability wrapped in clean, well-named, well-tested code is genuinely more dangerous than the same error in ugly code, because ugly code gets read suspiciously.
Defect rates measure the failures you notice. I lean on the observation that teams measuring defect rates on generated code mostly do not find a dramatic gap. That measures what surfaced this quarter. The failure mode agents are prone to, a quiet incorrect assumption that bites in eighteen months, is exactly the one that does not appear in that number.
Some intrinsic properties really do determine maintainability. A 4,000-line function is hard to change for everyone, always, regardless of who wrote it or who has read it. I have pushed the relational framing hard enough to imply the artefact does not matter, and there is clearly a threshold below which it does.
Trust is falling for a reason. Stack Overflow’s 2025 survey has developer trust in AI output dropping from around 40 percent to 29 percent. That is a large number of practitioners looking closely and liking what they see less. I am arguing they are misattributing what bothers them, which is a claim that requires more humility than the framing above shows.
“Read it in proportion to risk” does not scale past a point. At genuinely high generation volumes even the risky subset exceeds what a team can absorb. Beyond that point the only honest answer is to generate less into those paths, and that is an unpopular recommendation with no good tooling behind it.
The takeaway
Generated code is maintainable in every sense we have ever been able to compute. It is unread, and unread is a different problem with a different fix.
Improving the artefact is the intervention with the best-looking dashboard and the least effect. Making conventions mechanical, keeping intent recoverable, and reading deliberately where being wrong is expensive are the interventions that change the cost of the next correct change.
If you take one thing into next week: take the last three review comments you wrote that were about a convention rather than a bug, and turn one of them into a lint rule. That rule will outperform every quality score you buy this year.