Mehdi Akiki
Published on

AI Code Review Bottlenecks and How to Measure the Queue

Authors
  • Mehdi Akiki avatar
    Name
    Mehdi Akiki
    Twitter

Article · Measurement

Measure where pull requests are waiting before treating all review delay as slow reviewers. Time before the first useful review, an open review conversation, author rework, and a dependency on another change call for different next steps. Counting open requests alone hides those differences.

Imagine a team that fixes its slow CI. Agents produce more patches, but the oldest pull request still waits. The usual explanation is that humans cannot keep up. That may be true. It may also be waiting for a product decision nobody assigned.

The earlier team-productivity article discusses coordination more broadly. This example is narrower: make a small review-queue snapshot, use it to choose one intervention, then check whether that intervention helped the work move.

Define the stages before collecting the numbers

Use stages that the team can identify consistently:

StageStarts whenEnds when
First review waitRequest becomes ready for substantive reviewFirst useful review response arrives
Review windowReviewer and author are discussing an unresolved decisionChanges are requested, dependency is identified, or approval is given
Author reworkRequested changes are handed back to the authorRevised change is ready for review
Dependency waitA specific prerequisite prevents progressThat prerequisite is resolved

The review window is elapsed time, not minutes spent reading code. Someone might review for ten minutes and then wait a day for an answer. GitHub review timestamps alone do not measure their effort. Avoid labeling that whole day “active review time.”

Decide what counts as the first useful response. A bot saying it has started and an automatic reviewer assignment are not evidence that someone understood the change. Likewise, a draft request should not inflate the ready-for-review queue simply because it has been open for a week.

Record a transition whenever responsibility changes. If the author finishes a revision, the age of its new review wait starts there. Carrying forward the original request age is useful history, but it does not describe the current stage.

Take one labeled snapshot

The following snapshot is constructed. The request numbers, waits, and owners are illustrative; they are not measurements of this site's contributors.

RequestCurrent stageTime in this stageWaiting for
101First review wait27 hoursImport owner to accept the review
102Author rework11 hoursAuthor to add a missing retry case
103Dependency wait6 hoursA shared schema change to merge
104Review window20 minutesProduct decision on an error message

Keep the snapshot time next to the table. “27 hours” without an observation time becomes misleading as soon as someone revisits it. Include a link to the actual request in a real queue so an owner can correct a stale stage.

The small snapshot helper computes stage age from explicit transitions. It excludes draft entries and rejects unknown stages, duplicated request numbers, and future timestamps. It does not infer who is working from online status or message volume.

Its test for the first row uses a fixed observation time of October 24 at noon UTC and a transition at 09:00 the previous day. The expected difference is twenty-seven hours. That checks the age calculation. It does not validate the human judgment that this request is ready or that its owner is available.

Choose an intervention for the actual wait

Request 101 may need an accepted reviewer assignment. Ask whether the named owner can take it, and reassign through the team's normal process if necessary. Generating a fifth patch for that same owner would add work without resolving this wait.

Request 102 is already with the author. An agent could help add the requested retry case and update the explanation. Sending another review reminder would target the wrong person.

Request 103 needs a dependency decision. Perhaps the schema change can merge independently. Perhaps the application patch should wait rather than open overlapping alternatives. Name the prerequisite instead of describing the whole request as “slow review.”

Request 104 needs a product answer. More code reading may not produce it. Write down the two possible behaviors and get the responsible person to choose. The next diff can then implement that choice without guessing.

These are hypotheses to check with the people involved. A timestamp is a starting point for a conversation, not proof that an individual is underperforming.

Check movement without hiding the remaining work

For one week, record the same stages at a consistent time and follow the same requests. Note new arrivals, stage transitions, merges, and closures. If the oldest first-review wait shrinks only because requests were closed or returned to draft, say that. It is not equivalent to completed review.

Compare like cases where possible. A small label fix and a data migration have different review needs. An average across both can conceal where capacity is missing. The snapshot is deliberately small enough that the team can read the underlying requests instead of trusting one dashboard number.

A team might first try limiting new related requests while the current queue is overloaded. It could then use agents to answer review questions, reduce optional cleanup, or assemble missing evidence for the oldest ready change. DORA's small-batch guidance supports independently useful work; splitting a feature into disconnected fragments can increase the decisions reviewers must hold in mind.

Keep CI required while making these changes. The CI timing example separates machine feedback from the rest of the wait. A faster build and a shorter review queue are different outcomes, and the team needs to see both.

The next agent task can now be specific: help finish request 102's retry case, or explain request 103's dependency. There is a better reason for that task than simply having enough tokens to open another pull request.