Skip to content

How to Set Pull Request Size Limits for Open Source Projects

A 19,000 line-of-code pull request landed in Node.js core, and the community erupted. The debate quickly turned to whether LLM-assisted PRs should be banned entirely. But I think the real problem isn’t AI—it’s PR size.

The Real Problem

Large pull requests break code review. A 19K LoC PR is unreviewable by any reasonable standard. Reviewers miss bugs, security issues, and architectural problems because of cognitive overload. The result? Superficial “LGTM” approvals that put critical infrastructure at risk.

The Node.js community discussion made this clear. The top comment with 132 votes stated it plainly:

“Enforce maximum PR sizes with minimal exceptions, enforce test coverage, enforce code style, and enforce security. From there it won’t matter if it’s AI or not.”

Another comment with 27 votes:

“The only real problem here is PR size. 19K LOC is unreviewable by any reasonable standard. The fix is simple: enforce PR size limits and require contributors to demonstrate understanding during review.”

The consensus is clear: size limits solve the governance problem without banning AI assistance.

Here’s a practical framework I recommend:

Size CategoryLines ChangedAction
Small< 400 linesFast-track review
Medium400-1000 linesStandard review
Large1000-2000 linesRequire justification
Unacceptable> 2000 linesReject or require split

Automating Enforcement with GitHub Actions

Let me show you how to enforce these limits automatically. Create a workflow file:

.github/workflows/pr-size-limit.yml
name: PR Size Limit
on: pull_request
jobs:
check-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check PR size
run: |
ADDITIONS=$(gh pr view ${{ github.event.pull_request.number }} --json additions --jq '.additions')
DELETIONS=$(gh pr view ${{ github.event.pull_request.number }} --json deletions --jq '.deletions')
TOTAL=$((ADDITIONS + DELETIONS))
if [ $TOTAL -gt 2000 ]; then
echo "PR is too large ($TOTAL lines). Maximum is 2000 lines."
exit 1
elif [ $TOTAL -gt 1000 ]; then
echo "::warning::Large PR detected ($TOTAL lines). Consider splitting."
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

This workflow runs on every pull request and fails if the PR exceeds 2000 lines.

Using Danger.js for Richer Checks

For more sophisticated size checking with generated file exclusion, use Danger.js:

dangerfile.js
import { danger, warn, fail } from 'danger'
const totalLines = danger.github.pr.additions + danger.github.pr.deletions
if (totalLines > 2000) {
fail(`PR is too large (${totalLines} lines). Please split into smaller PRs. Maximum: 2000 lines.`)
} else if (totalLines > 1000) {
warn(`Large PR (${totalLines} lines). Consider splitting for easier review.`)
}
// Exclude generated files
const generatedFiles = danger.git.created_files.filter(f =>
f.endsWith('.generated.ts') || f.includes('node_modules')
)
if (generatedFiles.length > 0) {
console.log(`Excluding ${generatedFiles.length} generated files from size count`)
}

Adding Size Labels Automatically

You can also automatically label PRs by size:

.github/workflows/pr-size-labels.yml
name: PR Size Labels
on: pull_request
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add size label
uses: actions-ecosystem/action-add-labels@v1
with:
labels: |
size/${{ steps.size.outputs.category }}

Documenting Your Policy

Clear documentation is essential. Add this to your CONTRIBUTING.md:

CONTRIBUTING.md
## Pull Request Size Guidelines
We enforce size limits to ensure thorough code review:
- **Small (&lt; 400 lines)**: Preferred, fast review
- **Medium (400-1000 lines)**: Acceptable, standard review
- **Large (1000-2000 lines)**: Requires justification in PR description
- **Oversized (&gt; 2000 lines)**: Will be rejected; please split
**Tips for splitting large PRs:**
1. Separate refactoring from feature changes
2. Split by logical component/module
3. Create a tracking issue for multi-PR changes
4. Stack dependent PRs using GitHub's draft feature
**Exceptions:**
Generated code, dependency updates, and vendored files are excluded from line counts.
Request an exception by tagging a maintainer with a detailed justification.

Common Mistakes to Avoid

I’ve seen projects make these mistakes:

No Written Policy - Document size limits clearly. Unwritten rules create confusion and inconsistency.

Rigid Enforcement Without Exceptions - Allow exceptions with maintainer approval and documentation. Some changes (like vendored library updates) legitimately need to be large.

Counting Only Additions - Consider total lines changed (additions + deletions). A refactor that moves 500 lines should count, even if net additions are small.

Ignoring File Types - Exclude generated files, lockfiles, and vendored code from limits. They inflate counts without adding review complexity.

No Guidance for Splitting - Provide documentation on how to break down changes logically. Contributors want to help, but need direction.

Why This Matters

For critical infrastructure like Node.js or React, security vulnerabilities affect millions of users. Performance regressions have widespread impact. Trust in the ecosystem depends on code quality.

For project sustainability, size limits reduce maintainer burnout and encourage contributor onboarding. Smaller PRs have higher review quality, bugs are caught earlier, and changes are easier to understand and revert.

Summary

In this post, I showed you how to set pull request size limits for open source projects. You learned the recommended size categories, how to automate enforcement with GitHub Actions and Danger.js, and how to document your policy. The key is starting with clear limits, automating enforcement, and providing guidance for contributors.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments