software architecture

The Codebase Only AI Understands: Why 3am-Fixability Is the Metric Nobody's Tracking

AI coding assistants roughly doubled code duplication while cutting refactoring in half, and experienced developers report AI tools make them slower, not faster. The fix isn't banning AI-authored code — it's gating on one question: if the person who wrote this isn't on the call, can the on-call still fix it at 3am? A concrete diagnostic, not a moral panic, with three guardrails an architect can put in place this quarter.

13 min read
The Codebase Only AI Understands: Why 3am-Fixability Is the Metric Nobody's Tracking
Key Takeaway

A GitClear analysis of 211 million lines of code found AI coding assistants roughly doubled code duplication while cutting refactoring activity by about half, and a Stack Overflow analysis found experienced developers reporting a roughly 19% productivity decrease using AI tools — so the speed argument doesn't survive contact with the people qualified to judge it. "Codebases only AI understands" is already an emerging classification among practitioners; 3am-fixability is the sharper, gateable version of that same complaint. The fix isn't banning AI-authored code. It's pointing the belief good architects already hold — recoverability beats elegance — at the new place it needs to apply: can the on-call fix this at 3am without the person who wrote it?

The 2am page from an architecture that looked clean on paper

The design doc had a clean line for it: one service calls another, gets a response, moves on. No fallback. No queue in between. No circuit breaker. In the review, that was the elegant version — fewer moving parts, one clear path through the system, nothing to explain away. I signed off on it. It was my call.

It held for months. Then the downstream service slowed down under a load spike, and the synchronous call upstream started backing up behind it. No timeout worth mentioning. No fallback path. The single point of failure I'd rationalized in the design review — it's fine, that service is reliable, we don't need the complexity — was now the entire incident.

The page came at 2am. I was the only person who'd carry the full shape of that coupling in my head, because I was the one who'd approved it as "simple." Tracing it live, half-asleep, staring at logs that made sense to me and would have made sense to nobody else on the rotation, I understood something that no design review had ever made me feel: the diagram was clean because it hid the exact thing that was now on fire. A fallback would have cost a few extra lines and one more box on the whiteboard. Instead it cost a night, and it cost the on-call engineer — who happened to be me, but didn't have to be — the ability to fix it without picking up the phone to the person who built it.

That's the whole lesson, and it's not subtle: the room that reviews a design optimizes for elegance and consensus. The pager at 2am optimizes for whether a tired human can trace the failure and close it out alone. Those are different tests, and the industry has spent decades pretending they're the same one.

AI-generated code just found a faster way to fail the same test.

Naming the failure mode: what AI-only-legible code actually looks like

"Codebases only AI understands" is already circulating among engineers who work with AI-assisted codebases daily — its own flavor of tech debt, distinct from the usual "legacy mess." It deserves the distinction. It's a different shape of problem.

Architecturally, it looks like this: instead of one shared abstraction, you get three near-identical implementations of the same logic, each generated in a separate session with no memory of the other two. Instead of a module with a discoverable seam — a clear interface, an obvious place to extend it — you get a file that passes every test in the suite but has no natural entry point for a human trying to reason about it from the outside. It was legible to the model, in that session, with that context window loaded. Five files and two weeks later, it's legible to no one, including the person who prompted it.

This is where the GitClear finding stops being a vibe and becomes a measurement. Their analysis of 211 million lines of code found that AI coding assistants roughly doubled the rate of code duplication in committed code, while refactoring and moved-code activity — the signal that someone went back and consolidated duplicated logic into a real abstraction — fell by about half. That's a fitness-function failure: a measurable property of the system's shape trending in exactly the wrong direction, at the exact moment more code is entering the codebase, faster than ever.

But it shipped faster — the objection this article exists to kill

Here's the objection, and it's a fair one to raise before dismissing it: none of this matters if the velocity gain is real. Duplication is ugly, sure, but if AI-assisted teams are shipping meaningfully faster, maybe untidy code is the acceptable cost of speed — the same trade every fast-moving team has made since before AI existed.

A Stack Overflow analysis of developer survey data undercuts that trade before it gets made. Experienced developers — the people with enough context to actually judge whether AI tools were making them faster — reported a roughly 19% productivity decrease when using AI tools, not an increase. Not neutral. Negative, for the group most qualified to notice.

If the speed premium doesn't survive scrutiny from the people best positioned to measure it, then judging AI-authored code by how fast it went green was always the wrong instrument. You can't spend a velocity gain you don't actually have to buy a maintainability cost you're already carrying.

The stakes: untraceable code is a security surface

Duplicated code offending an architect's sense of order would be a craft-purity argument on its own. Untraceable code is also a security surface — and the numbers on that are worse than the duplication numbers.

Research estimating the security posture of AI-generated code found that approximately 45% of AI-generated code samples carry an OWASP Top 10 vulnerability. Now connect that back to the duplication pattern from the last section: in a codebase where AI-authored logic gets duplicated instead of consolidated into a shared, reviewed abstraction, a vulnerable pattern doesn't get fixed once. It gets copied into every near-identical implementation sitting next to it, unnoticed, until someone finally traces the pattern back.

The line to the on-call is direct, and it's the one that should worry an architect more than the aesthetics: the engineer paged at 3am may be sitting on top of an unpatched vulnerability that nobody flagged, not because nobody cared, but because nobody could read the module well enough to flag it. Untraceable code doesn't just cost you a slow incident. It costs you the ability to know what you're exposed to before the incident happens.

3am-fixability: the one metric worth gating on

I've been circling one question since the opening scene, and it's worth stating precisely, because it's the only term in this piece worth remembering: if the person who wrote this isn't on the call, can the on-call still fix it?

That's 3am-fixability. Test coverage doesn't answer it. Neither does review approval, or how fast it shipped. A tired human, cold, with no access to the mind — human or model — that produced the code, has to be able to trace the failure and close it out alone. If they can't, the architecture failed, regardless of what the design review or the CI pipeline said about it.

This is Belief B-05 — the right architecture is the one your on-call can fix at 3am without you — applied to a failure surface I didn't have a decade ago. The diagnosis hasn't changed since the night that coupling paged me. What's changed is who's doing the clean-on-paper rationalizing. It used to be me, in a design review, choosing the simpler diagram. Now it's sometimes a model, mid-session, optimizing for "this satisfies the prompt and passes the tests" with no concept of who reads it next. Same mistake. Faster author. The fix is the same belief I already paid to learn, pointed at a new place it can hide.

Three guardrails an architect actually owns

None of this requires banning AI-assisted development, and none of it requires a new tool vendor. These are three things an architect can put in place directly, this quarter, without asking anyone's permission to try AI at all.

Cap the blast radius with interface contracts, not trust

Define the contract at the seam — inputs, outputs, invariants — around every module where AI wrote a meaningful share of the logic. Not the function signature; the invariant. What must always be true when this module hands control back, and what happens if it can't guarantee that. You don't need to distrust the code inside the boundary. You need the contract at its edge strong enough that a failure inside an AI-authored module can't propagate past it and become the whole incident. You don't need to be able to read every line to know the blast radius stops at the wall you built around it.

Put the duplication finding into CI as a fitness function

This is the direct, gateable answer to the GitClear pattern, and it's a different instrument than a linter. A linter checks syntax and style at a point in time — is this line formatted correctly, right now. A fitness function tracks a structural trend across commits — is this module's duplication-to-refactor ratio moving in the wrong direction over recent PRs, specifically in AI-flagged or AI-heavy commits. Track it per module or per PR. Warn on it first if a hard gate feels premature. But track it, the same way you'd track error budgets or latency percentiles — a number that moves, that you can put a threshold on, that isn't a feeling in a retro.

The test that actually matters: could the on-call read this without the author?

This is the practical instrument for 3am-fixability, and you can run it this week. Take a module or service that went through a heavy AI-assisted session recently. Pull in someone who was not the author and was not in that session — cold. Ask them to trace the logic: what does this do when its input is malformed, what's the failure path, where would they even start if this paged them tonight. If they can trace it in a reasonable amount of time, it passes, whatever tool wrote it. If they can't — if the honest answer is "I'd have to find whoever wrote this" — it fails review, full stop, regardless of test coverage, regardless of how fast it shipped. This is the cold-read test, and it costs one meeting and one honest engineer willing to say "I don't understand this" out loud.

Recoverability still beats elegance — it just has a new opponent

Design for the tired human who has to fix it, not for the room that approves the diagram. That's the belief this piece has been arguing for all along — B-05 didn't need updating for the AI era. It needed pointing at a new place to hide.

This is the opening piece of a three-part argument about architecture discipline in the AI era. The same instinct — check before you add a layer you can't cheaply take back — is what makes most teams reach for multi-agent orchestration before they've earned the complexity. And the leadership version of the same shift is the closing piece: why cost, not quality, is now the AI accountability question. For that same "check before you add it" instinct applied to a single feature instead of a whole system, see designing LLM-powered features for production, and for the regression-safety net a shipped feature needs, building an evals-based regression net.

Monday morning: what to actually do

Pick one AI-heavy module or repo from your last sprint and run the cold-read test this week. Find someone who wasn't in the authoring session, give them the module cold, and time how long it takes them to trace a failure path. That single data point will tell you more than a retro conversation about "AI code quality" ever will.

Add one duplication or refactor-ratio check to CI, scoped to AI-flagged commits or a directory you already suspect. Start it as a warning if a hard gate feels too aggressive for where your team is. The point is that the number exists and someone is watching it move.

Find the last AI-generated service or module that merged without a written interface contract, and write one now. Not the function signature — the invariant. What has to remain true at that seam no matter what changes inside it. These are instruments you own directly as the architect. None of them require a tooling vendor, a new process owner, or permission from anyone above you.

Frequently asked questions

What is 3am-fixability?

It's a one-line test for whether an architecture decision — or a piece of AI-generated code — is actually sound: if the person who wrote this isn't on the call, can the on-call still fix it? If the answer is no, the code or the design failed, regardless of how it performed in review or in CI.

How do you actually test for 3am-fixability?

Run the cold-read test: hand the module to someone who wasn't the author and wasn't in the AI session that produced it, and have them trace a failure path with no help. If they can do it in a reasonable window, it passes. If they can't, it fails review, independent of test coverage or how fast it shipped.

Is this an anti-AI argument?

No. It's a diagnostic for whether a piece of code — AI-authored or not — can survive a cold read by someone who wasn't in the room when it was written. Plenty of human-authored code would fail the same test; AI just produces the failure at higher volume and higher speed, which is exactly why it needs a gate instead of a vibe check.

How is an architectural fitness function different from a linter or a code review checklist?

A linter and a checklist evaluate a single point in time — is this line formatted correctly, did this PR follow the template. A fitness function tracks a structural trend across commits, like a rising duplication-to-refactor ratio in AI-flagged code over recent PRs, and it can gate a build the same way a latency or error-budget threshold does.

Doesn't this slow AI-assisted development back down?

It adds friction at the seams where friction is cheap — a contract here, a duplication check there, one cold-read session per sprint. That's a fraction of the cost of the incident you avoid, and it's far cheaper than the roughly 19% productivity decrease experienced developers already report in Stack Overflow's survey data, with none of these guardrails in place.

Where should these guardrails live — with the AI tooling team or the architects?

With the architects. Tooling teams can supply the AI assistants and the CI infrastructure, but deciding where the interface contracts go, what counts as an acceptable duplication trend, and who runs the cold-read test is an architecture decision. It's the same ownership an architect already has over on-call recoverability — this is just the newest place that ownership needs to show up.

If you've had your own 2am page from a decision that looked clean in the room — or you want to try the cold-read test on your own team this week — reply and tell me how it went.

#software-architecture#ai-generated-code#technical-debt#code-quality#ai-engineering#architecture-fitness-functions#on-call#code-review#2026
Ruchit Suthar

Ruchit Suthar

15+ years scaling teams from startup to enterprise. 1,000+ technical interviews, 25+ engineers led. Real patterns, zero theory.

Continue Reading

Application Availability: How Many Nines Do You Need?

Application Availability: How Many Nines Do You Need?

Application availability decoded honestly: what 99%, 99.9%, 99.95%, 99.99%, and 99.999% actually allow in downtime, the two formulas that calculate it, why every extra nine costs roughly 10x the last, how dependencies in series cap your ceiling before your effort does, and SLA/SLO/SLI/error budgets. The argument underneath it all: past four nines for most teams, the number that saves your night isn't a bigger percentage — it's how fast you recover.

·20 min readRead now
Retrieval Failure vs Generation Failure: How to Diagnose Which Layer Is Killing Your RAG System

Retrieval Failure vs Generation Failure: How to Diagnose Which Layer Is Killing Your RAG System

A retrieval-augmented system that answers wrong failed in exactly one of two places — the retriever handed the model garbage, or the model had good material and still wrote garbage. They look identical from the outside and need completely different fixes. This is the diagnostic discipline that stops teams from rewriting prompts for six weeks while retrieval is quietly broken: measure retrieval on its own, then generation on its own, in that order — and fix the layer that's actually failing instead of the one that's cheapest to edit.

·14 min readRead now
Evals for LLM Features: Building the Regression Net for a Non-Deterministic Dependency

Evals for LLM Features: Building the Regression Net for a Non-Deterministic Dependency

You can't ship a reliable LLM feature on vibes. Evals are the regression net for a dependency that's non-deterministic, drifts when the provider updates the model, and fails silently. How to build one without boiling the ocean: start with 30 real examples, layer three kinds of checks (assertion, LLM-as-judge, human), measure faithfulness, and run it on every prompt, model, and retrieval change.

·11 min readRead now