Guide 3 of 5

Too many AI pull requests to review? Limit the queue

Last updated

The problem

A pull request (PR) is a proposed change to your code that waits for someone to review it and merge it in. A draft pull request is one that is marked as not ready to merge yet. An unattended AI agent works through your tickets and leaves a draft PR for each one, so a person can check the work before anything reaches your product.

The agent can start a new ticket every half hour, day and night. Your reviewers can't keep up with that. They have their own work, meetings and time off. Reading a change carefully, running it and deciding whether it's right takes real time, whoever wrote it.

So the bottleneck moves. It used to be writing the code. Now it's reviewing it. If nothing links the two speeds, the review queue grows every day, and the agent keeps adding to a pile nobody can get through.

Review queue with and without a limitTwo panels. Without a limit, the agent adds a new draft every run: the first two are reviewable, the next three are going stale and the last three conflict with other work. With a limit of two, the agent opens two drafts and then pauses, and the remaining tickets wait without being started.No limita new draft every runDraft 1Draft 2Draft 3Draft 4Draft 5Draft 6Draft 7Draft 8ReviewableGoing staleConflictingThe queue grows every runLimit of 2the agent pauses at the limitDraft 1Draft 2LimitAgent pausedTicket waitsTicket waitsTicket waitsNot started, nothing spent
Without a limit, the queue keeps growing. With one, extra tickets wait unstarted and cost nothing.
  1. No limit: the agent opens a new draft on every run, and the queue keeps growing.
  2. The first two drafts are reviewable. Drafts three to five are going stale. Drafts six to eight conflict with other work.
  3. Limit of two: the agent opens two drafts, reaches the limit and pauses.
  4. The other tickets wait in the backlog without being started, so nothing is spent on them yet.

Why a pile of drafts goes bad

A big review queue isn't just slow. The drafts in it get worse while they wait.

Each draft starts from a copy of your main code as it was when the agent picked the ticket. Programmers call that copy a branch, and the main code the base branch. While the draft waits, the rest of your team keeps changing the base branch. The draft doesn't change with it, so it falls further behind. That's what stale means here.

Stale drafts cause two kinds of trouble:

  • Conflicts. If two drafts change the same part of the same file, the first one to be merged makes the second one clash. Git calls this a merge conflict. Someone has to untangle it by hand before the second draft can go in.
  • Wrong assumptions. A draft written against last week's code may rely on something that has since changed. Even without a conflict, it can be quietly wrong, and the reviewer now has to check it against today's code, not the code it was written for.

The more drafts wait, and the longer they wait, the more of this cleanup there is. An agent that opens twenty drafts in a week can leave your team with more work than it saved.

Two drafts going stale and conflictingA timeline of the base branch over five days. Drafts A and B both branch from it on day 1. Other people's changes land on days 2 to 5. Draft A is merged on day 4. Draft B, which changed the same file, now conflicts and is four changes behind.Base branchDay 1Day 2Day 3Day 4Day 5Draft ADraft BA merged on day 4ConflictDraft B: same file as A,four changes behinda change by someone else
Drafts that wait fall behind the base branch, and the first to land can break the next.
  1. Day 1: drafts A and B both start from the base branch as it is that day.
  2. Days 2 to 5: other people’s changes land on the base branch. The drafts don’t move with it.
  3. Day 4: draft A is reviewed and merged.
  4. Draft B changed the same file as A. It now conflicts and is four changes behind, so a person has to fix it before it can land.

The fix: a limit on open drafts

The answer is backpressure. The term comes from plumbing: when a pipe downstream is full, pressure pushes back and slows what's coming in. For an AI agent, it means the agent only starts new work when your team has room to review it.

In practice, it's one number: the most drafts from the agent that can be open at the same time. Before each run, the agent counts its open drafts.

  • If the count is below the limit, it can pick a ticket and work on it.
  • If the count has reached the limit, it doesn't start anything. It's paused.
  • When a person merges or closes one of the drafts, the count drops, and the next check can start a run again.

Nobody has to switch the agent off or on. The pause and the resume both follow from your team's own pace. If your reviewers land three drafts a day, the agent does about three tickets a day, however often it's scheduled to check.

The pause-and-resume loopEvery half hour the launcher checks whether the agent's open drafts are below the limit. If yes, it starts one run, which opens a draft and adds it to the review queue. If no, it pauses and nothing starts. When a person lands a draft, the count drops and the next check can start a run.Launcher checkevery 30 minBelow the limit?count open draftsyesStart one runone ticketDraft PRcount +1Review queuewaits for younoPausednothing startsYou land a draftcount −1room again: the next check can run
The agent's pace follows your review pace, not its schedule.
  1. Every half hour, the launcher checks the count of open drafts.
  2. If the count is below the limit, it starts one run, which works one ticket.
  3. The run opens a draft PR, which joins the review queue. The count goes up by one.
  4. If the count is at the limit, the agent pauses. Nothing starts and nothing is spent.
  5. When you land or close a draft, the count goes down by one, and the next check can start a run again.

A pause is cheap if the count happens early. The best place to check is before anything expensive starts: before a machine is switched on and before the AI model is called. Then a paused agent costs close to nothing, and the tickets it didn't start are still there for later.

Technical detail: what counts as an open draft

The count only makes sense if it matches what your reviewers actually have to deal with. A few rules keep it honest:

  • Count the agent's pull requests only. The agent's branches follow a fixed naming pattern, so they're easy to tell apart from your team's own work. Your team's PRs don't use up the agent's allowance.
  • Count per repository. Drafts in one repository don't conflict with drafts in another, so each repository gets its own count. A full repository is passed over, and another repository with room can still get a run.
  • Merged or closed leaves the count. Closing a draft you don't want is as good as merging one, as far as the limit is concerned. If you merge the branch on your own machine and push it, GitHub marks the pull request as merged automatically, so nobody has to tidy it up by hand.
  • The schedule is only an upper bound. A check every 30 minutes allows at most 48 runs a day. With a limit in place, the real number is set by how many drafts you land.

Choosing the limit for your team

The right limit is roughly the number of drafts your team can properly review in a working day. Too high, and you're back to a growing pile. Too low, and the agent sits idle while reviewers are free.

These are starting points, not measured figures. Adjust them once you've seen how your team actually works:

Your teamStarting limit
One person, reviewing now and then1
One person who reviews most days2
A few people sharing reviewsAbout one per regular reviewer
A larger team with a review rotaWhat the rota clears in a day, and no more

Then watch two signs:

  • Raise it if drafts are usually reviewed the same day and the queue is often empty.
  • Lower it if drafts regularly wait more than a couple of days, or often need fixing because the base branch moved on.

Keep the limit lower if the agent's tickets touch the same parts of your code. Two drafts in the same file are the ones most likely to conflict.

The limit also works alongside your spending caps. A monthly budget stops runs when the money runs out. A draft limit stops them when your reviewers are full, which usually happens first. See what an AI coding agent costs per ticket for the money side.

Pick the newest tickets first

Once the agent is paced by your reviews, each run is worth more. So it matters which ticket it picks when it does run.

It's tempting to clear the backlog from the bottom, oldest first. For an agent, that's the wrong way round. An old ticket is the one most likely to be stale itself. It may describe code that has since been rewritten. It may already be fixed, with the ticket left open by mistake. The person who wrote it may have moved on, so nobody can confirm what it meant.

On one of our own repositories, 3 of 5 hand-picked "top tickets" were already in production. They looked important only because the tracker still said they were open. Picking by most recent update favours tickets someone still cares about, written against code that still looks like that.

Newest-first versus oldest-first pickingA backlog of five tickets sorted by when they were last updated, from today to fourteen months ago. Newest-first picks the ticket updated today, which matches the current code. Oldest-first picks the one from fourteen months ago, whose code has moved on and which may already be fixed.Backlog, by last updateUpdated today2 days ago3 weeks ago5 months ago14 months agoNewest firstmatches today's codeOldest firstcode has moved onsomeone still caresfresh contextmay already be fixedauthor may be goneAges are an example
Oldest-first picks the tickets most likely to be stale themselves.
  1. A backlog of tickets, sorted by last update: today, 2 days ago, 3 weeks ago, 5 months ago and 14 months ago (example ages).
  2. Newest-first picks the ticket updated today. It matches today’s code and someone still cares about it.
  3. Oldest-first picks the ticket from 14 months ago. The code has moved on and it may already be fixed.

Newest-first doesn't mean old tickets are ignored forever. Updating a ticket, for example by clarifying it or adding a comment, moves it back up. That's a useful habit anyway: a ticket worth doing is usually worth a quick check that it still makes sense. For what a ticket needs before an agent can work it, see is this ticket ready for an AI coding agent?

Technical detail: skipping tickets that are already done

Newest-first reduces stale picks but doesn't remove them. Two cheap checks catch most of the rest before any money is spent:

  • A recent commit claims the ticket. If a change on the base branch in the last 30 days says it fixes this ticket, the work is probably done. A passing mention doesn't count, only a commit that names the ticket as its own.
  • The ticket cites code the base branch doesn't have. If the ticket points to a specific commit that isn't on the base branch, the ticket describes work still sitting on someone's own branch. A fresh copy of the code won't match it.

In both cases, the right response is to skip the ticket quietly and log why. The ticket isn't wrong. It just isn't the agent's to run.

In practice with BacklogBeast

BacklogBeast is built around this limit. Here's how it works today:

  • The default limit is two open drafts per repository. BacklogBeast counts its own open pull requests in each repository before it does anything else for that repository's tickets.
  • The count comes before any spend. A repository at its limit is passed over before the readiness check, before a virtual machine starts and before the AI model is called. A paused repository costs nothing in model spend.
  • It resumes on its own. BacklogBeast checks every half hour. When you merge or close one of its drafts, the next check can start a run. Merging on your own machine and pushing counts too.
  • Newest first, never oldest first. It takes the most recently updated ready tickets, skips any that recent commits say are already done, and runs a readiness check on the rest.
  • Drafts only, never merged. Every pull request is opened as a draft, which GitHub won't merge. A person always decides what lands. See letting an AI agent open pull requests safely.

In our own use, the draft limit usually stops runs before the monthly budget does. That's the point: the agent works at the speed your team can review, and the backlog waits safely until you're ready. If you'd like to try it on your own repositories, join the waitlist.

Technical detail: the order of checks before a run

For each repository, in order, BacklogBeast's launcher asks:

  1. Is there at least one open issue with the ready label and no blocking label? If not, move on. This is the most common reason nothing runs.
  2. Are this repository's open agent drafts below the limit? If not, the repository is recorded as backlogged and passed over.
  3. Has a recent commit already claimed the ticket, or does it cite commits the base branch doesn't have? If so, skip it quietly.
  4. Does the ticket pass the readiness check? Only the newest few candidates are judged on each attempt. Tickets that fail are sent back to a person with a note saying what's missing.

Only then do the budget and timing checks run and a machine start. The ticket check comes before the draft count because it's the one that usually says no, and both are cheap reads from GitHub.