The Review Bottleneck
The situation around agent-assisted software development reminds me of the passage in Code Complete where McConnell discusses the importance of being aware of your location in a given “technology wave.” We are still at the early edge of this AI-driven wave, and we are experiencing many of its symptoms: rapidly changing tools, new workflows without settled conventions, and engineers spending time figuring out the tooling rather than simply using it.
A lot has changed in the last year or so. We have all seen the surge in plausible-looking, agent-generated code. Pull requests have grown much larger and arrive much faster. A 2,000-line change can now be put up for review after a few hours. On top of that, polish is no longer a proxy for code quality. The problems in code are not typos, but unnecessary abstractions or mistaken assumptions made early in the design. The PR author may not have read every line they are putting up for review, never mind carefully reasoning through it as they would hand-written code. The reviewer may be the first human to read the code closely.
Unfortunately, code review has not evolved at the same pace as code generation. Human review is becoming a bottleneck—but that gives us an opportunity to reconsider what code review is actually for.
Even prior to agents, I found a disconnect between what engineers thought the purpose of code review was and what actually ended up being valuable. Teams expect reviews to be about finding defects, but they really serve to facilitate knowledge transfer and allow alternative solutions to be considered (Bacchelli and Bird, 2013). In that context, maybe we are automating the smaller benefit and risking the larger ones. Automated review may already be more effective at catching local or mechanical issues than a hurried human, but it quietly eats away at learning until knowledge transfer goes to zero. After all, if we see a green check on a PR, do we really expect to consistently dedicate time to deeply understand it at the expense of our own work?
What Human Review Is For
The question we ought to ask ourselves in the middle of all this development acceleration is how do we reimagine many things we took for granted… If you ask me, the way we do code review today makes less and less sense, and the same is true for pull requests. — Venkat Venkataramani, VP @ OpenAI
The software development lifecycle is evolving so quickly that predicting its eventual shape is probably ill-advised. But there is no question that PR review needs a redesign. My sense is that much of today’s review process will eventually become infrastructure, much as type systems and CI have offloaded work. I can see engineers being a different kind of QA, one step up stream. Like QA, we are increasingly reviewing work done by another party to ensure it meets certain criteria. In the current environment, and possibly for many years, there are a few principles we can keep in mind.
Below I’ll outline some things that I believe matter in human review including ownership, conceptual integrity, and learning, as well as ideas for structuring the changes so that a person can realistically achieve these goals. To start here are some questions I keep in mind as I review code changes.
Does this duplicate an existing abstraction?
A human who has worked in the codebase for years may recognize where an abstraction already exists. With heavily agent-generated code, that is less likely to be caught. Agent-generated PRs show almost twice the semantic redundancy (the same logic expressed through different code) as human-authored ones (Huang et al., 2026). Reviewers are also more lenient and less likely to question this redundancy. Duplication is one of the cardinal sins in programming, so it’s easy to see how this bloat could lead to issues over time.
If you want a system to have conceptual integrity, then somebody has to be looking at the whole system. — Martin Fowler
Is someone (ideally the author) able to defend the changes?
Agents aren’t yet on the hook for responding to incidents, so we as programmers must be able to debug the changes. Using an agent changes who typed the code, not who owns it. Saying “the agent wrote it” in a postmortem means we delegated too much. If we aren’t confident that we understand the changes, they should not be merged. Questions raised during review may be evidence that a change is not yet understandable enough to merge, so they are important to raise.
Does the change fit well in the codebase?
If we take a rubber-stamp approach to code review, we forfeit the ability to control the conceptual integrity of the codebase. Agents are great at producing many independent and uncoordinated changes. Without human oversight, the codebase can quickly devolve into a patchwork of duplicative and incoherent code. Code review is one of the places where we can course-correct individual changes and keep the system’s design intentional.
I will contend that conceptual integrity is the most important consideration in system design. — Fred Brooks, The Mythical Man-Month
What can the team learn from this change?
The reasoning behind a design is often missing from the final diff. These choices are especially important for junior engineers and new hires to learn from. When engineers are handed only the final output, they have no way to learn how to evaluate tradeoffs and grow their expertise. Deliberately discussing those tradeoffs also prevents others from having to repeat the same decision-making process later.
Are the tests sufficient?
If we are reading and writing less of the code, we need high-quality tests to mitigate the risks. Tests have always been the safety net that lets us make changes without breaking things, and at the scale code can now be changed, they’re even more important. Thankfully, tests are also much easier to write with AI. We should review them as carefully as the production code to make sure the agent isn’t simply maximizing coverage. I still find some tests that feel “tautological”—they simply assert the implementation itself rather than verifying any meaningful behavior (e.g. a test that checks that a constant defined in a method has the value it was assigned). Another common failure is heavily mocked tests that are unable to exercise any real behavior.
With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse. — Michael Feathers, Working Effectively with Legacy Code
Sizing and Scoping Changes
Of course, none of this works if the change is too large to understand.
How can we reduce the size of changes?
Research conducted well before the current generation of coding agents found that defect detection declined as reviews grew beyond roughly 400 lines (Cohen, Best Kept Secrets of Peer Code Review, SmartBear/Cisco). We’re now asking more reviewers to do more than just scan for bugs, so I think 400 lines is still a good threshold to aim for. I exclude whitespace, generated files, comments, and tests from this informal count.
But splitting large features into reviewable chunks has always been a challenge. Feature work doesn’t get done in clean, independently reviewable pieces. Agents actually can help with this problem. We can continue iterating until the work is functionally ready in whatever process we prefer, then ask an agent to help organize it into manageable chunks instead of publishing one large PR with a messy history. There are a few ways to do this.
Atomic Commits
Once the work is done, ask the agent to rewrite the commit history on the feature branch (before anyone has pulled and built off of it) so that each commit focuses on one aspect of the change. For instance, model or API changes could be in one commit, UI behavior in another, and tests alongside the behavior they verify. These can be put up together so the reviewer sees the whole picture while retaining the ability to view each commit in isolation. This optimizes for comprehension by preventing the reviewer from having to scroll back and forth in the code review tool past unrelated changes. It also requires very little effort from the author and lets them keep their own workflow, with just a simple cleanup step added.
The end result is that the commits are grouped conceptually rather than chronologically. Instead of showing what order the changes were made in, they are organized into coherent sets that better explain what is being changed.
Stacked Diffs
If your team or workflow fits better with decomposing changes so that each can actually be reviewed and merged independently, then stacks are an alternative approach. Companies like Uber and Meta have used these for years. GitHub added its own gh stack tooling on July 2026. There are many other offerings available such as Graphite. They all help with managing the branches, but more importantly also with all the relationships between them, rebasing/restacking, and merging. This guide has a good overview of how these work.
Independent PRs
If you can divide a change into entirely independent sets of work that can land in isolation, that can often be the best approach. This may involve making preparatory PRs that refactor existing code to be open to extension (the “O” in SOLID), followed by architectural changes and then the behavioral change itself. The final PR can contain the interesting, unique functionality while the earlier PRs contain the more mechanical changes.
Offloading Cognitive Load
There are also steps beyond organizing the change sets themselves that we can take to help out our coworkers as they try to get a handle on changes we put up for review. The goal should be to reduce the amount of context that the reviewer has to mentally reconstruct in order to understand the change.
Automate the First Pass
Having a standardized team protocol that is followed before asking for human review is helpful for keeping routine issues out of the way. I recommend using a shared set of role-specific agents focused on specific tracks such as concurrency and testing to catch mistakes a general-purpose coding agent may overlook. Paul Hudson hosts some nice ones here. If you have access to multiple families of models for reviews, differences in their training data can mean they find slightly different problems too. I like having all of this run via a single pre-review skill that can be invoked just before pushing changes. Agent review pipelines are a topic in their own right that I will cover in a future post, but sharing a process across the team helps raise the bar for the code and makes our reviews more efficient.
Give Reviewers a Map
PR descriptions can add a lot of value for readers. One of my goals is to transfer the context that I gathered through iterating on the implementation so that each reviewer picking it up from scratch doesn’t have to struggle to recreate it (or worse, skip trying). I like to include a reading guide that explains which files matter, which are mechanical piping, how they fit together, and what order to read them in. Any additional narration of the mental model behind the change can only help the reviewers learn. This shouldn’t just be more generated text, but a short, thoughtful, ideally human-written or edited introduction.
Including other modalities like images and diagrams can also be extremely effective. For UI changes, before-and-after screenshots or recordings communicate the high-level intent immediately, making the details easier to understand. For non-UI changes, simple Mermaid diagrams can be very helpful and can generally be rendered directly. For those unfamiliar, Mermaid is essentially Markdown for diagrams. I like adding flowcharts or decision tables showing how behavior changes across scenarios (e.g. to model online and offline states, errors, or retries). They are almost always much easier to understand than nested conditionals or paragraphs of commentary.
In Closing
AI has made it much cheaper to produce code. It has not made it cheaper to understand a system, preserve its conceptual integrity, or take responsibility when something goes wrong. Who knows whether that will continue to be true forever, but for now the goal is still more useful software—not merely more code.

