How Software Development ChangedLesson 14 of 87

Contents

How Software Development Changed

Lesson 14 of 87. Sign in to keep your place.

Module 2 · Reading what you did not write

Why the diff has to be small

9 min read

Defects found per line, as a review grows05101002000lines in one reviewdefects found per hundred lines—— The shape every inspection measurement has foundThe thresholds vary by study, language and team, so these numbers are the shape rather than yours.What is not in doubt is that detection per line falls monotonically, with no size at which a reviewerbecomes efficient.
The thresholds vary by study, language and team, so these numbers are the shape rather than yours. What is not in doubt is that detection per line falls monotonically, with no size at which a reviewer becomes efficient.

Figure

The curve everybody in review has felt

The practitioner literature on code inspection (most of it originating in studies of large industrial teams and popularised through inspection tooling vendors) reports two consistent findings, and they have been quoted so often that it is worth stating them with proper hedging. Defect detection per line falls sharply once a single review passes somewhere in the range of a few hundred lines, and it falls sharply again once a review session runs beyond about an hour. The specific thresholds vary by study, by language and by domain, and the numbers you see quoted are averages over settings that may not resemble yours.

What is not in doubt is the shape. Detection per line goes down as review size goes up, monotonically, in every measurement anyone has made. There is no plateau where a reviewer becomes efficient at scale.

That curve was always true. What changed is that producing a 2,000-line change now takes minutes, so the norm that used to be enforced by the cost of typing has to be enforced deliberately.

What a large diff does to a reviewer, mechanically

It is not laziness. It is capacity.

Understanding a change means holding a model of the before-state and the after-state in mind simultaneously and comparing them. That model has to include the invariants: what was guaranteed before, what is guaranteed now. Every additional file adds to the model, and the models interact, so the cost is superlinear rather than linear.

At some point the model no longer fits, and what a reviewer does then is switch strategy without noticing. They stop comparing states and start pattern-matching on the lines: does this look like reasonable code? That is the exact check that generated code passes trivially. So a large diff does not merely reduce the amount of review. It converts review into the one form of review that no longer works.

How to actually split

“Make smaller pull requests” is advice everyone has heard and few follow, because the mechanics are the obstacle. Three that work:

Separate the refactor from the change. This is the highest-value split and the easiest to sell. First a commit that moves and renames things with zero behaviour change, verified by the existing tests. Then a commit that changes behaviour, which is now twenty lines instead of four hundred. The reviewer reads the second one properly because it is readable.

Stack the branches. Branch B off branch A, open both, and note the dependency. Most git hosts show only the incremental diff for the second one. GitHub, GitLab and the git-town and graphite style tools all support this; so does plain git if you rebase carefully.

Bash
git switch -c 1-add-currency-column main
# ... commit ...
git switch -c 2-use-currency-in-total 1-add-currency-column

Land it dark. Merge the new code behind a flag that is off, in one reviewable piece, then flip it in a two-line change. The reviewer of the big piece knows nothing is live; the reviewer of the two-line piece knows exactly what changes.

Set a number and enforce it in CI

A soft norm dissolves under deadline. A number in a pipeline does not.

YAML
# fail the build on very large diffs, with an explicit override label
- name: diff size
  run: |
    n=$(git diff --numstat origin/main...HEAD \
        | grep -vE '(lock|\.snap|generated/)' \
        | awk '{s+=$1+$2} END {print s+0}')
    echo "changed lines: $n"
    test "$n" -lt 500 || test "${OVERRIDE:-}" = "true"

Exclude lockfiles, snapshots and generated directories, because they are noise and blocking on them teaches people to ignore the rule. Provide a documented override, because there are real exceptions (a dependency bump across a hundred files, a formatter run, a genuine bulk rename) and a rule with no escape hatch gets disabled entirely within a month.

The counter-argument, which is real

Splitting has a cost. Five stacked pull requests mean five review cycles, five CI runs, five context switches, and a merge order somebody has to remember. On a team where review latency is already three days, five sequential reviews is more than two weeks for one feature, and that is a worse outcome than one large review.

So the honest rule is conditional. Small diffs pay off when review turnaround is fast. If review takes days, splitting makes delivery worse, and the thing to fix first is the latency, which takes you back to the queueing lesson. The two problems are linked and solving them in the wrong order makes both worse.

Every lesson here is open. Your progress is recorded once you pass the AI at Work exam.

Check your understanding

A team introduces a 400-line cap on pull requests. Review latency is currently four days. Six weeks later, feature delivery has slowed. What is the most likely explanation?

Pick the one you would defend. Your answer stays private.

Next lesson · 10 minReading a test suite you did not write

Stuck on something?Ask Larissa, your AI tutor

How to cite: Addaly (2026) ‘Why the diff has to be small’, in How Software Development Changed. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/how-software-changed/diff-size-economics (Accessed: 13 October 2026).