RSS Amplifier

5-Minute DevOps · Mar 4, 2026

AI Broke Your Code Review. Here’s How to Fix It

0
Sign in to vote or save

Bryan Finster · 5-Minute DevOps

When I started using AI-generated code as my primary development flow, it became immediately apparent that code review was broken. Not degraded. Broken. The process that worked reasonably well for human-authored code simply did not hold up when the rate of code production jumped by a factor of three or more.

To be clear: code review was always problematic. Lean practitioners have been pointing this out for years. Value stream maps make it hard to ignore: work that takes a few hours to produce, sitting in a review queue for hours, followed by back-and-forth debate via review comments with additional wait times. Asynchronous review is one of the most reliably wasteful steps in a software delivery pipeline, and there has always been a credible argument that pairing is a better answer. Synchronous collaboration catches problems earlier, at lower cost, without the queue. That debate never got resolved because the review process seemed manageable. AI made it unmanageable.

More people are sounding the alarm on this now, which is good. But I keep seeing the same response: add more scrutiny, tighten the checklists, pull more senior engineers into the queue. That is treating a systems problem like a staffing problem. It will not work.

This is an engineering problem. It has an engineering solution rooted in lean principles and continuous delivery practices. A recent LinkedIn post called this out: “AI did not eliminate the coding bottleneck. It just moved it to a different part of the process.” The answer is not more human review. The answer is to automate all the things that can be automated, and reserve human judgment for what genuinely requires it.

Dave Farley recently applied the Nyquist-Shannon sampling theorem to this problem, and it reframes the issue in a way that is hard to argue with. The theorem holds that to accurately represent a signal, you must sample it at least twice as fast as the highest frequency in that signal. Applied to software delivery, this means your defect detection rate must exceed your production rate, or you will miss problems not occasionally but systematically. As Farley puts it, “if things are changing rapidly, you need to check them even more rapidly. You can’t check inadequately and expect to catch problems.”

AI produces code at high frequency. Manual code review is a low-frequency sampling mechanism. You increased production frequency without increasing feedback frequency. That is the definition of under-sampling, and under-sampling means you will miss problems. Not occasionally. Reliably.

Adding more human reviewers to a blocking queue does not fix this. You cannot hire your way out of a sampling rate problem. Humans reading diffs have a ceiling. SmartBear’s analysis of a Cisco Systems team puts it at 400 lines, past which defect detection degrades sharply. A single AI-assisted feature can blow past that in one prompt. That ceiling is not going up, no matter how many reviewers you add. The solution is to automate feedback so the sampling rate actually matches the production rate.

There is a second problem compounding the first. AI-generated code arrives in larger chunks. A developer prompts for a feature, gets back 600 lines, reviews it casually, and opens a PR. Beyond the 400-line threshold, you are not getting a review. You are getting a rubber stamp.

So the review queue is longer, each item in that queue is harder to review well, and the code itself has failure modes that standard review checklists were not written to catch. AI-generated code often looks right, but it lacks context: organizational conventions, edge cases from tribal knowledge, integration quirks with legacy systems, and taste. Syntax is fine. Logic hangs together. The reviewer approves. Six weeks later, someone discovers that the AI-generated abstraction ignored the one integration quirk that everyone who has been on the team longer than a year knows about.

When you map review categories against what can actually catch each one, the blocking human gate earns very little of the checklist. Here is what reviewers are routinely expected to catch but reliably miss:

  • Syntax and style: inconsistently flagged, consumes attention that should go to harder problems.

  • Security flaws: the attack surface is too large and too subtle for manual inspection at scale.

  • Logic bugs: human reviewers miss logic errors in large diffs. Past 400 lines, detection degrades sharply.

  • Architecture drift: spotting a boundary violation requires knowing the intended architecture. Most reviewers don’t have that context loaded when they open a diff.

  • Performance regressions: no reviewer can benchmark in their head. Diffs don’t reveal latency or memory pressure.

  • API breaking changes: downstream consumer impact isn’t visible in a diff.

Added to these problems are the new challenges AI creates more rapidly than humans:

  • Meaningful names: AI naming looks syntactically valid but loses semantic intent. A reviewer who didn’t write the code often can’t tell that processData is doing something it shouldn’t.

  • Architectural boundaries: AI doesn’t know your hexagonal architecture. It generates code that works, not code that respects your layer boundaries.

  • Documentation drift: code changes faster than documentation. Reviewers rarely review documentation and may not know it exists, let alone whether it’s now wrong.

  • AI-specific bloat: AI code follows patterns that look architecturally sound. Unnecessary abstractions, single-use factories, redundant indirection, etc. It passes inspection because it resembles patterns reviewers recognize as good.

Each of these has an automated alternative that catches the problem earlier, faster, and more consistently than a human reading a diff.

Standard tooling covers the first six. Linters and formatters own syntax and style. Static analysis and dependency scanning own security. Automated tests own logic bugs, if you write tests that matter. Fitness functions own architecture drift. Contract testing owns API breaking changes. Automated performance suites own regressions.

The last four are where standard tooling falls short. AI-generated code has failure modes that general-purpose tools weren’t built for. Automated semantic naming review catches identifiers that obscure intent. Domain boundary analysis and structural coupling checks detect layer violations and hexagonal architecture breaches. Automated documentation drift detection diffs changed code against related docs and flags gaps at commit time, when the author still has full context. Automated AI antipattern detection targets the structural over-engineering patterns AI models reliably produce.

After automation handles all of that, the list of what genuinely requires a human to block a merge is short.

The first category is tribal knowledge: the integration quirks, the historical decisions, the “we tried that and it broke payments” context that lives in people’s heads and nowhere else. The honest long-term fix is to capture that knowledge in documentation and architecture decision records, then enforce it with tooling. The short-term reality is that you need a human who knows where the bodies are buried, and their job is reviewing for context, not syntax.

The second is regulated paths. In environments where separation of duties is a compliance requirement, a second human must approve changes to sensitive areas. That is not negotiable. But it is also not an argument for applying the same standard to every PR in the repository. Reserve the blocking gate for what actually requires it.

Code review was designed to catch mistakes, not deception. Malicious code is specifically engineered to evade it. A developer with bad intent spreads behavior across multiple unrelated PRs, hides logic in utility functions, obfuscates intent through naming, and exploits reviewer fatigue on large diffs. That last point circles back to batch size being a security issue, not just a throughput issue.

The XZ Utils backdoor is the clearest modern example. A long-term contributor spent two years building trust, embedded a backdoor across multiple commits, and a researcher found it by accident, not through code review. For regulated environments, the question worth asking is not “was this reviewed?” It is “Could any single actor have introduced this change undetected?” Code review does not answer that question. Dependency scanning, reproducible builds, signed commits, and immutable audit logs do.

Before worrying about reviewer capacity, fix the source. A recent LinkedIn post framed the gate as: “If the author can’t explain every line, it’s not ready for someone else to review.” The gate is stated as “explain every line,” but what really matters is: can you articulate the behavior, the intent, and the edge cases? That is the right standard.

What actually matters is whether the author understands what the code does: the behavior, the intent, the edge cases, the integration points. Not the implementation details of every generated loop. An author who can articulate what changed, why, what it is supposed to do, and what the tests verify has done the work. An author who can recite the internals of an AI-generated sort routine but has not thought about the downstream contract has not.

Automated tooling makes this practical. Tools that run on every file write, checking naming, complexity, test coverage, architectural boundaries, and AI-specific failure modes, give the author feedback before the PR exists. By the time the code reaches the review queue, it has already been through a checklist tuned to the actual failure modes of AI-generated code. Findings, not raw diffs. A focused job, not a broad one.

A fair question came up when I shared this framing: if AI generates the code and AI reviews it, where is the human oversight? Who is doing the acceptance testing?

The question assumes oversight happens at review time. It doesn’t. Or at least, it shouldn’t. The most important set of eyes is the team that defined the behavior before a single line of code was written.

This is the point of BDD: we sit down as a team before coding starts and define what the behavior should be as executable scenarios. Those scenarios become the acceptance tests. They are the team’s shared definition of done, written in plain language and committed to the repository before anyone opens an IDE. No single developer decided what the system should do. The team decided. The AI is then implementing a specification that already has multiple sets of human eyes on it.

That changes what review is for. A review is not where you discover whether the behavior is correct; your acceptance tests already define what is correct. A review checks whether the implementation respects your conventions, boundaries, and constraints. That is a much smaller job, and a much more focused one.

The second answer is batch size. Small batches are not just a throughput preference. They are what makes human oversight feasible. A developer working in small increments with AI, verifying each chunk against the executable specification before it becomes a PR, is exercising more genuine oversight than a reviewer rubber-stamping a 900-line diff at the end of a sprint.

AI-generated code is not a special case. It goes through the same delivery process as any other change: the same automated tests, the same CD pipeline, the same deployment gates. The concern that AI output needs more scrutiny than human-written code is understandable, but it misdiagnoses the problem. The pipeline validations that should have caught these issues all along were never implemented. Human review was substituting for them. AI didn’t remove a safety net. It revealed that the safety net was always a person performing heroics somewhere in the process. If your acceptance tests cover the behaviors that matter, they tell you whether the system is correct, not just whether the syntax compiles. If those tests don’t exist or don’t cover the behavior in question, that is the problem to fix, and it predates AI.

What AI actually did was expose teams that were already relying on code review as their primary quality process. If review is where you discover whether the implementation is correct, you never had a real quality process. The review should be a quick validation that the solution aligns with the specification that the team agreed on. When it is carrying the full weight of quality, it was always going to collapse under load. AI just increased the load fast enough that the collapse became impossible to ignore.

The human reviewer is still in the loop. They review agent findings rather than raw code. Humans judge context. Agents surface candidates. The reviewer decides which findings matter, which are false positives, and which reveal something the tooling could not have known. That is meaningful oversight. It is just not the same as reading every line of a 600-line diff and hoping to spot the problem.

Define behavior as a team before coding starts. Keep the batches small. Run the same process for every change. That is how you get real oversight at AI speed.

Farley’s conclusion is the one to keep: “if you increase production frequency, you must increase feedback frequency or your system will fail.” AI increased production frequency. The feedback mechanisms stayed the same. That is the problem.

Adding human reviewers to the queue is not increasing feedback frequency. It is adding latency to a low-frequency mechanism and expecting different results. Automating the feedback that can be automated, reserving humans for what only humans can catch, and raising the sampling rate with tooling is how you close the gap.

Teams that add human reviewers to a broken sampling mechanism will watch quality decline while throughput stays flat. The math doesn’t change because you hired more people.

SmartBear, “Best Practices for Peer Code Review” (Cisco Systems data): defect detection degrades sharply past 400 lines of diff.
XZ Utils backdoor analysis: https://www.akamai.com/blog/security-research/critical-linux-backdoor-xz-utils-discovered-what-to-know
Dave Farley, “AI Coding and the Nyquist Theorem”:

No posts

Read the original on bryanfinster.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.