Fifty pull requests in a week

A week of deliberately high throughput, and the bottleneck was never typing speed. Notes on small diffs, review latency, and safe velocity.


I spent a week trying to ship as many pull requests as I responsibly could, half as an experiment and half because the backlog had gotten personal. Fifty merged later, the lesson wasn’t the one I went in expecting. The constraint on throughput was never how fast I could write code. It was everything around the code: review latency, branch hygiene, the half-hour tax of switching context, and the slow accretion of work-in-progress nobody had finished.

Velocity turns out to be a property of your workflow, not your fingers. Teams that ship fast aren’t typing faster. They’ve removed the friction between “this change is done” and “this change is live,” and that friction hides in strange places.

Small diffs are a velocity technology

The biggest single change was shrinking my pull requests. A 600-line PR sits in review for a day because no reviewer wants to start it. A 40-line PR gets reviewed in the gap between two meetings because the cost of looking is nearly zero. Review latency tracks diff size far more closely than diff difficulty, and in most teams review latency is the whole bottleneck.

Small diffs compound. They merge faster, so they conflict less, so rebasing is cheap, so the next one ships sooner. They’re easier to revert, so shipping them is less scary, so you ship more readily. They isolate failures, so the bisect is short when something breaks. The system speeds up because each unit of work is small enough to flow through it without clogging.

There’s a floor, though. Below about ten lines you’re paying more in PR ceremony than the change is worth, and I spent a day of that week opening PRs that should have been one PR. Nobody warns you about that end of the curve.

One task, one branch, one PR

The second thing that mattered was refusing to let work pile up in the working tree. Every task got a branch off the latest main, did exactly one thing, and opened exactly one PR. No “while I’m in here” detours. No two features sharing a branch. No half-finished experiment sitting on top of a finished fix.

# start clean off the latest main, every single time
git fetch origin main
git switch -c fix/specific-thing origin/main

# ... one focused change ...

git push -u origin fix/specific-thing
gh pr create --fill   # one task, one PR

Sounds rigid. It’s liberating. When each branch is one task an in-progress change never blocks a finished one, you just switch branches. When a review comes back with comments you address them in isolation instead of untangling them from three other things you’d started in the same tree. That discipline is what let me keep a dozen changes in flight without any of them stepping on the others.

Speed is safe only when the net is automatic

None of this would have been responsible without tests and CI doing the worrying. Shipping fifty changes by hand-verifying each one would have been reckless. Shipping fifty where every one ran the full suite and couldn’t merge red was just fast.

That trust has to be earned first. A flaky suite is worse than no suite, because it teaches you to ignore red, and a team that ignores red eventually merges something genuinely broken. My week worked because the suite was fast and honest. Green meant safe, red meant stop, and there was no third state where I had to use judgment about whether a failure was real.

I don’t think the throughput number matters much on its own. What stuck was noticing how much of my old pace was self-inflicted: big diffs I was proud of, branches I let sprawl, a suite I half-trusted and therefore double-checked by hand. Fixing those three things cost nothing and I’d been paying for them for years.