The Science of the Small Pull Request
A 40-line PR gets three thoughtful comments. An 1,800-line PR gets 'LGTM'. That's not laziness — it's arithmetic. Here's what batch size does to review quality, and how to slice.
Two pull requests landed on the same team, the same week. The first changed 42 lines; it collected three substantive comments, one of which caught a real off-by-one at a pagination boundary. The second changed 1,847 lines across 31 files; it sat for two days, accumulated one comment — "looks good, one nit on naming" — and merged. Six weeks later, the incident review for a data-corruption bug traced the root cause to file 24 of 31.
Nobody on that team was lazy. The reviewer of the big PR was the same careful engineer who caught the off-by-one in the small one. What differed wasn't diligence. It was dose. And the relationship between review dose and review quality is one of the few things in our field where we have actual evidence, so let's take it seriously.
What the research says
The best-known data comes from a large study of code review at Cisco, published in Best Kept Secrets of Peer Code Review (SmartBear, Jason Cohen and colleagues). Two findings matter here. First, defect discovery falls off sharply as review size grows — the guidance that emerged was to review no more than about 200–400 lines of code at a sitting, because beyond that, the rate at which reviewers find problems drops substantially. Second, effectiveness also degrades with time-in-session: after roughly an hour of continuous reviewing, attention decays and defects start sliding past.
The mechanism is exactly the working-memory story I keep returning to in this column. A reviewer isn't reading lines; they're maintaining a mental model — what changed, what invariants hold, what this function promises callers — and checking each hunk against it. Every additional file stretches the model. Somewhere past a few hundred lines, the model collapses, and the reviewer, usually without noticing, switches strategies: from verifying the change to skimming for anomalies. Skimming catches typos and style. It does not catch the subtly wrong invariant in file 24.
There's even a name for the resulting artifact in engineering folklore: the "LGTM of despair." Ask a reviewer for ten minutes and you get analysis. Ask them for four hours and you get approval.
Batch size, from the factory floor
Software borrowed this insight late; manufacturing has known it for decades. A central lesson of lean production — the deep reason behind one-piece flow — is that large batches hide defects and delay their discovery. If you stamp 10,000 parts before inspecting one, a miscalibrated press means 10,000 bad parts. Small batches shorten the feedback loop, so errors surface while they're cheap.
A pull request is a batch. A large PR doesn't just review poorly; it flows poorly:
- It waits longer. Reviewers can find ten minutes today for a small diff; they defer the monster to "when I have a block of time," which is to say Thursday.
- It merges riskier. More surface area means more ways to conflict, more behaviors changing at once, and — when something breaks — a wider suspect list. The most valuable property of a small PR appears at 2 a.m.:
git revertof one small commit is a scalpel; reverting a fortnight of intertwined work is surgery with oven mitts. - It feeds a vicious cycle. Slow reviews teach engineers to batch more work per PR "to make the review worth it," which slows reviews further. Teams don't decide to have a big-PR culture; they drift into it, one rational-seeming decision at a time.
And a contemporary note: AI assistance has made large diffs dramatically cheaper to produce. It has done nothing to make them cheaper to review. When generation accelerates and verification doesn't, the queue in front of your reviewers becomes the constraint on the whole system. Guard it.
One intent per change
Size is the headline, but the deeper virtue is purity. The real unit of reviewability isn't lines — it's intents.
A 300-line PR that does one thing ("extract the pricing rules into a strategy object — no behavior change") reviews faster than a 100-line PR that does three ("fix the rounding bug, rename the module, and bump the linter"). The reviewer of the mixed PR must classify every hunk before evaluating it: is this line a behavior change or part of the rename? That classification work is pure extraneous load, and it's where mistakes hide — a behavior change smuggled inside a "just a refactor" diff is nearly invisible, because the reviewer has been lulled into pattern-matching renames.
Kent Beck's Tidy First? makes the discipline concrete: separate tidying (structure changes that preserve behavior) from behavior changes — different commits at minimum, ideally different PRs, with the tidying landing first. The refactor PR gets reviewed with one question ("is this really behavior-neutral?") and the feature PR gets reviewed with another ("is this new behavior right?"). Each question is answerable. Blended, neither is.
My favorite phrasing of the rule: a reviewer should be able to state your PR's intent in one sentence without using the word "also."
Practical tactics for slicing
"Make PRs smaller" is easy to say and genuinely nontrivial to do. Some tactics that work:
Stack your changes. Build the feature as a chain of dependent PRs: interfaces first, then implementation, then call sites, then cleanup. Each link reviews in minutes. Modern tooling has made stacked workflows far less painful than they once were.
Land scaffolding dark. Merge new code paths behind a feature flag or unused entry point, in small pieces, before the switch-flip PR — which then becomes tiny and thrilling instead of huge and dreaded.
Preparatory refactoring first. In the spirit of a line long associated with Beck: make the change easy, then make the easy change — with the crucial addendum that the making-it-easy warrants its own PR.
Slice vertically when you can. A thin end-to-end slice (one field, one endpoint, one screen state) reviews better than a horizontal layer ("all the models") because the reviewer can evaluate a complete behavior rather than trusting that a future PR will use all this plumbing correctly.
Budget, don't ban. Some changes are irreducibly large — generated code, vendored dependencies, sweeping mechanical renames. Fine. Label them as such, isolate them from judgment-requiring changes, and keep the human-attention-requiring portion of any PR inside the few-hundred-line envelope where review actually works.
Homework
- Measure your team's PR size distribution — most platforms expose it. Just making the median visible changes behavior.
- Next feature, write the PR titles first. Sketch the sequence of 3–5 single-intent PRs before you write code. It's a design exercise disguised as project management.
- Apply the "also" test to your next PR description. If the summary needs "also," split it.
- As a reviewer, name the dose. It is professional, not rude, to say: "This is too large for me to review well. Can we split it at the refactor/behavior seam?" You are protecting the author from your own skimming.
Review attention is the scarcest renewable resource on a team. Small, single-intent PRs aren't a bureaucratic nicety — they're how you spend that resource where it can still buy something.