The Review Metrics Most Teams Don't Track

Most teams can tell you their velocity. Almost none can tell you their review quality — and three real bugs, plus one ticket that only looked like codegen, show exactly why that gap matters now that AI writes a growing share of every PR.

Vineet Arya · October 2026

An illustration of a review checklist where several items are quickly checked off, but one item is circled in gold as flagged for closer attention — representing the difference between a fast rubber-stamp pass and a real review.

Most engineering teams can tell you their velocity. Almost none can tell you their review quality. That gap used to be survivable. Once AI started writing a meaningful share of the code going into every PR, it stopped being survivable — and most teams don’t yet have a way to even see the problem, let alone measure it.

This is a field guide for the leader who already feels this gap and needs a concrete place to start.

The pattern nobody wants to say out loud: bigger MRs get less review, not more

I haven’t instrumented this formally yet, but the pattern is consistent enough to act on: the bigger the merge request, the less real review it tends to get. Not because reviewers are lazy — because a 45-file diff is cognitively expensive to hold in your head, deadline pressure doesn’t pause for its size, and “approve” is one click regardless of whether you read line 40 of file 38.

Here’s the rough shape of review time I’ve observed, by diff size:

A bar chart showing review time growing disproportionately with merge request size: 1 to 5 files takes 10 to 20 minutes, 6 to 12 files takes 30 to 45 minutes, 12 or more files often takes over an hour, and 40 or more files can take 3 to 4 hours.
Not instrumented — based on felt experience, not a formal benchmark.

That last number is the uncomfortable one. Almost nobody budgets 3-4 hours for a single review. So large AI-assisted MRs — exactly the ones most likely to contain something a smaller, hand-written change never would have — are often the ones getting the fastest, thinnest pass.

One practical mitigation worth trying: use AI to help review large AI-generated MRs. Ask it to draw a flow diagram of what the diff actually does, or to list edge cases the change should handle. This genuinely helps compress review time on big diffs. But it’s not free — querying AI for this kind of review assistance eats into the same token budgets and rate limits your team is already managing, which creates a real, underappreciated tension: the tool that helps you review faster is itself a constrained resource.

The actual metric: review-time-to-author-time ratio

(Worth being precise on naming — “build time” collides with CI/CD pipeline terminology. This is about authoring time: how long it took to write the change, not how long it takes to compile.)

Track this by MR size band, not as one blended number. If the ratio is shrinking — review time staying flat or dropping while MRs get bigger and more complex — that’s the concrete, measurable version of “our review capacity hasn’t kept pace with what AI lets us produce.” It’s a lagging indicator you can act on before it becomes an incident.

Three real bugs that made it through review — and what each one actually teaches

1. The environment-parity gap

An engineer on my team moved a heavy page’s data into a static JSON file generated at build time, specifically to cut page load time. Smart optimization. It worked perfectly in local development. It broke in production — because the static file needed to be added to a production-side access control allow-list, and that step never happened. Nobody caught it in review, because the review looked at the code, not at “what’s different between where this was tested and where it’ll actually run.”

The review question this adds: for any change touching build output, caching, or access configuration — what’s different between the environment this was verified in and the environment it’s shipping to?

2. The duplication that only showed up at 50+ files

Our team had an explicit rule: reuse an existing component if one already exists, don’t create a new one. While building a new site, AI generated multiple near-identical copies of a reusable component — a CTA button, used with the same functionality and theme but slightly different variants on different page sections — instead of parameterizing one shared version. It wasn’t caught at review time, because the MR touched 50+ files and the team was under real launch pressure. It became a real problem months later, when a new requirement meant updating that CTA’s label and behavior — and we had to find and fix it in every duplicated copy instead of one place.

The review question this adds: on any large AI-assisted diff, explicitly ask — did this create new components that duplicate something that already exists, or should exist as one shared thing?

3. The trailing whitespace that broke a lab integration

This one happened to a senior engineer, which is exactly why it’s worth including — this isn’t a juniority problem. We were integrating a third-party learning platform’s lab environments into an educational product, with lab URLs entered by content creators through a CMS. Weeks after launch, we started seeing failures. Root cause: a content creator had left a single trailing space at the end of a URL field. When the URL was read and authenticated against, the extra whitespace broke it. It passed code review. It passed QA. Nobody — not the developer, not the reviewer, not QA — had thought to ask what happens with malformed input on a human-entered field.

The review question this adds: for any field populated by a human (not just API input), what happens with leading/trailing whitespace, empty values, or slightly malformed input? This is a negative-case question, and negative cases are exactly what both AI-generated code and fast reviews tend to skip.

The one that isn’t a bug: when a “codegen ticket” is actually a judgment ticket

This is the subtlest lesson, and I think it matters more than the three bugs above.

We had a ticket that looked, on the surface, exactly like something to hand to an AI agent: wire up catalog cards to link through to their product pages, generate the routes, map the slugs. A launch date was real, so we let the agent take the bulk of it.

What the ticket actually was: two separate content records representing the same underlying program — one used by the catalog card, a different one used by the product page — connected only by a naming convention, not a real reference between them. That’s not a routing problem. That’s a judgment call about data modeling that happened to be disguised as a routing problem.

A comparison between tickets that look like simple code generation tasks and tickets that are actually judgment tasks in disguise, such as reconciling two systems connected only by a naming convention rather than a real reference.
Before you hand it to AI, ask which one this is.

We didn’t put a junior engineer on it. If we had, they’d have been the person who hit the first slug mismatch, who understood why a specific validation safeguard existed in our codebase, and who could tell a content-ops person “these two records aren’t actually the same entry, even though they look like they should be.”

Instead, the gap surfaced weeks later, on a different team, who needed a knowledge-transfer document to understand the system. The first line of that document had to be “read this if you take away nothing else.” That sentence is the missing ramp. The code shipped. The owner didn’t.

The practical test before handing a ticket to AI: is this actually a codegen task, or is it a judgment task wearing a codegen task’s clothes? If reconciling two systems, two data models, or two teams’ assumptions is part of the real work, that’s exactly the kind of rep a junior engineer should still be getting — not because AI can’t do the typing, but because nobody develops the judgment to catch the next version of this problem without having done it once, by hand, under supervision.

Accountability, as it honestly stands today

Right now, on my team, the default accountability model is simple: the engineer is responsible for development, review, and QA of anything they ship, AI-assisted or not. If it breaks, that’s on the engineer — the expectation was always that AI-generated code gets reviewed and regression-tested like any other code.

I want to be honest that this is a starting point, not a finished governance model. It doesn’t yet answer the harder question underneath it: what happens when you use AI to review AI-generated code.

Two real problems sit inside that, not one. The practical one: querying AI to help review large diffs (flow diagrams, edge-case prompts) draws on the same token budgets and rate limits your team is already managing — a genuinely expensive habit to build at scale, not a free upgrade. The deeper one: an LLM reviewing another LLM’s output is notoriously better at catching localized syntax issues than organizational context or architectural drift. If neither the model that wrote the code nor the model reviewing it has the context to question a flawed underlying assumption, you can get two confident passes and still miss the thing that actually mattered. The tool that helps you approve code faster can quietly become a co-signer on a bad decision.

Both of these are real and, as far as I can tell, not well-solved anywhere yet.

If you only take three things from this

  1. Track review-time-to-author-time ratio by MR size band, not as one number. Watch for it shrinking as diffs grow.
  2. Ask two questions on every review, regardless of size: what’s different between where this was tested and where it’ll run, and what happens on malformed or negative input?
  3. Before a ticket goes to AI, ask whether it’s actually a judgment task wearing a codegen task’s clothes — not every routing or data-mapping ticket is one, but when reconciling systems, data models, or assumptions is the real work, that’s a rep worth protecting, not just work worth automating.

A note on who this is for

This is written for the engineering manager or lead who’s in the work daily and feels this gap already. If you’re a Director or VP a layer removed from day-to-day review, your real need is different — a dashboard view across sprint velocity, burndown, bug-fix-vs-reported rate, SLA breaches, bug categories (security, compliance, data integrity), and repeat-bug rate. That’s a genuinely different piece, and one worth writing once I have the same kind of real, specific material behind it that made this one worth publishing.


None of the incidents above are hypothetical. Details have been genericized to protect confidentiality, but the failure modes, the review gaps, and the lessons are real.


Vineet Arya is an engineering leader focused on AI adoption and governance, with 18+ years building software.

"Judgment doesn't compress — everything else does."