runmypr Guides · Mergestorm affiliate Try it free

Guides · Practices

How big should a pull request be? Size limits that speed up review

Published Oct 6, 2026 · ~9 min

A large pull request split into smaller ones

Short answer: aim for around 100–200 changed lines of real logic per pull request, treat 400 as the point where review quality drops, and treat 1,000 as too large. Size is the single biggest lever on how fast a PR gets reviewed, and the one authors control completely.

What the guidance says

The two agree on the shape: small changes get reviewed sooner and more carefully. Google’s reason is practical: it is “easier for a reviewer to find five minutes several times” than a 30-minute block.

What real PRs show

We measured time to first human review against PR size on the last 100 merged PRs in facebook/react (Oct 6, 2026), using our free script:

Lines changedPRsMedian waitp75 wait
0–50296.9h18.4h
51–200453.5h24.8h
201–400133.7h12.6h
401–1,000719.7h22.1h
1,001+544.4h2.8d

Up to about 400 lines, size does not predict how fast React’s PRs get picked up; the smallest PRs actually waited a little longer, and all 87 PRs up to 400 lines together had a median wait of 4.5 hours. Past 400, the median wait jumps roughly fourfold, and past 1,000 it is nearly two days. The large buckets are small samples, so treat the exact numbers loosely, but the cliff lines up with the guidance above. Run the script on your own repo; your cliff may sit somewhere else.

Why big PRs wait

How to split a big change

Separate refactoring from behavior

The most common bloated PR is a feature plus the cleanup needed to build it. Ship the rename, move or extraction first as its own PR with no behavior change. It reviews in minutes because the reviewer only has to confirm nothing changed.

Stack dependent PRs

Google calls this stacking: send one small change for review, then immediately start the next one on top of it. Reviewers see a chain of small diffs instead of one huge one, and you are never blocked waiting.

Split by layer

Schema and migration, then the API, then the UI. Each layer can be reviewed by the person who knows it best.

Ship dark behind a flag

Merge incomplete work behind a feature flag that is off in production. You can merge small pieces daily without users seeing a half-built feature.

Keep generated files out of the count

Lockfiles, snapshots and generated code inflate line counts without adding review work. Mark them as generated in .gitattributes (package-lock.json linguist-generated=true) so GitHub collapses them in the diff.

Make size visible: a size-label Action

Nobody remembers a size limit. A label on every PR makes size visible without blocking anyone. Save this as .github/workflows/pr-size.yml:

name: PR size
on:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  issues: write         # creating labels
  pull-requests: write  # labeling the PR
jobs:
  label:
    runs-on: ubuntu-latest
    steps:
      - name: Label by lines changed
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR: ${{ github.event.pull_request.number }}
          ADDED: ${{ github.event.pull_request.additions }}
          DELETED: ${{ github.event.pull_request.deletions }}
        run: |
          lines=$((ADDED + DELETED))
          if   [ "$lines" -le 50 ];   then size=XS
          elif [ "$lines" -le 200 ];  then size=S
          elif [ "$lines" -le 400 ];  then size=M
          elif [ "$lines" -le 1000 ]; then size=L
          else size=XL; fi
          gh label create "size/$size" -R "$REPO" --force >/dev/null
          for s in XS S M L XL; do
            if [ "$s" != "$size" ]; then
              gh pr edit "$PR" -R "$REPO" --remove-label "size/$s" 2>/dev/null || true
            fi
          done
          gh pr edit "$PR" -R "$REPO" --add-label "size/$size"

It counts generated files too, so a lockfile bump can land in size/L. Start with labels, not a failing check: a hard limit pushes people to split PRs in ways that make them harder to review. After a month, look at how long size/XL PRs waited compared with size/S; that comparison persuades a team better than any rule.

Forks: PRs from forks get a read-only token, so the label step fails there. For open-source repos, run it on pull_request_target instead, which is safe here because the job never checks out the PR’s code.

When a big PR is fine

Say so in the description (“mechanical rename, no logic change”) so the reviewer knows how to read it. Everything else: if it is over 400 lines, ask whether it is really one change. For more author-side tactics, see how to get pull requests reviewed faster.