Post Image
githubDec 15, 2025

The GitHub PR Review Process That Actually Works for Our Team

Ruchi Yadav
Ruchi Yadav8 min read

We used to have a problem. Pull requests would sit for days waiting for review. When reviews came, they were either rubber stamps or nitpicking sessions about code style. Nobody was happy.

Sound familiar? If you've worked on a team larger than three developers, you've probably experienced this pain. PRs pile up like dishes in the sink, blocking deployments and frustrating everyone involved. The worst part? When reviews finally happen, they often miss the important stuff while obsessing over semicolon placement.

So we changed things. It took a few months of experimenting, several heated retrospectives, and more than one "emergency PR review session," but we found a process that works. Here's what we do now—and more importantly, why it works.

Small PRs Only: The Foundation of Fast Reviews

This was the biggest change. We set a soft limit of 400 lines of code per PR. Big features get broken into multiple PRs that build on each other. It felt slower at first, but reviews are faster and more thorough now. Nobody wants to review 2000 lines of changes.

Why 400 Lines Works

Research shows that review effectiveness drops dramatically after 400 lines. Your brain simply can't maintain focus on that much code at once. We learned this the hard way when a critical bug slipped through a 1,500-line PR that three people had "reviewed."

Here's how we break down larger features:

  • Database changes first: Schema migrations and model updates in their own PR
  • API endpoints second: New routes and controllers, depending on the schema changes
  • Frontend integration third: UI components that consume the new APIs
  • Polish and optimization last: Performance improvements and edge case handling

Making Small PRs Work in Practice

The key is structuring your branches properly. We use a pattern like this:

text
feature/user-notifications
├── feature/user-notifications-db
├── feature/user-notifications-api
├── feature/user-notifications-frontend
└── feature/user-notifications-polish

Each branch builds on the previous one, but can be reviewed independently. The "parent" branch (`feature/user-notifications`) gets merged only after all the pieces are in.

Pro tip: Include context in your PR description about where this fits in the larger feature. Something like: "This is part 2 of 4 for user notifications. Adds API endpoints that will be consumed by the frontend in the next PR."

Automate the Boring Stuff

We stopped arguing about formatting. Prettier runs automatically. ESLint catches common mistakes. Tests run before anyone looks at the code. Human reviewers focus on logic, architecture, and whether the code actually solves the problem.

Our Automation Stack

Here's what runs on every PR before human eyes see it:

  • Prettier: Handles all formatting automatically
  • ESLint + TypeScript: Catches syntax errors, unused variables, type mismatches
  • Unit tests: Must pass with 80%+ coverage on new code
  • Integration tests: For any API changes
  • Security scanning: We use CodeQL for vulnerability detection
  • Performance regression tests: For any database query changes

This automation eliminates about 60% of the comments we used to leave. No more "missing semicolon" or "inconsistent spacing" feedback that just annoys everyone.

Setting Up Effective Pre-commit Hooks

We use `husky` and `lint-staged` to run these checks before code even reaches the PR:

json
{
"lint-staged": {
"*.{js,ts,tsx}": [
"prettier --write",
"eslint --fix",
"git add"
]
}
}

The result? PRs arrive in a consistently formatted, lint-free state. Reviewers can focus on what actually matters.

The 24-Hour Rule: Keeping Things Moving

If a PR sits for more than 24 hours without a review, it becomes anyone's priority. We take turns being the "reviewer of last resort." It sounds strict, but PRs move fast now. Most get reviewed within hours.

How We Track and Enforce This

We use a simple Slack bot that posts daily reminders about stale PRs. The message includes:

  • PR title and author
  • How long it's been waiting
  • Who's assigned as the backup reviewer

Here's what a typical reminder looks like:

"
Stale PRs Alert 🚨

>

"
- "Add user authentication middleware" by @sarah (31 hours) - backup: @mike
"
- "Fix memory leak in image processing" by @alex (26 hours) - backup: @jessica

The backup reviewer system ensures nothing falls through the cracks. We rotate this responsibility weekly, so it doesn't become one person's burden.

Making the 24-Hour Rule Sustainable

The key is setting realistic expectations. If your team is constantly missing the 24-hour mark, the limit might be too aggressive for your current capacity. Start with 48 or 72 hours and work your way down.

Also, we have exceptions for:

  • End-of-week PRs: Get until Monday afternoon
  • Holiday periods: Extended to 48 hours
  • Large refactoring PRs: Pre-negotiated timeline with the team

Better Feedback: Making Reviews Constructive

We agreed on comment prefixes. "nit:" means optional suggestion. "question:" means I am curious but not blocking. "blocker:" means this needs to change before merging. It removes a lot of guesswork about how serious a comment is.

Our Complete Feedback Framework

Here are all the prefixes we use:

  • `blocker:` - Must be fixed before merge
  • `question:` - Seeking clarification, not necessarily blocking
  • `nit:` - Optional improvement, author can ignore
  • `suggestion:` - Recommended change, but not required
  • `praise:` - Positive feedback (yes, we make this explicit)
  • `security:` - Potential security concern (always treated as blocker)
  • `performance:` - Potential performance impact

Examples of Effective Review Comments

Instead of: "This is wrong."

Write: `blocker: This method doesn't handle the case where user.email is null, which will cause a runtime error in the email validation step.`

Instead of: "Consider using a map here."

Write: `suggestion: A Map might be more performant here since we're doing frequent lookups. But the current approach is fine for the expected data size.`

Instead of: "Good work!"

Write: `praise: Nice abstraction here! This makes the error handling much cleaner and more reusable.`

We also try to include at least one positive comment per review. It sounds cheesy, but it helps. Code review should not feel like an interrogation.

The Power of Constructive Feedback

Positive feedback does more than just make people feel good—it helps junior developers understand what "good code" looks like. When you call out a clever solution or clean abstraction, you're teaching by example.

Common Pitfalls We Learned to Avoid

The "LGTM" Trap

"Looks good to me" without any substantive comments usually means the reviewer didn't really look. We now require reviewers to leave at least one specific comment—even if it's praise for something well done.

Bikeshedding in Reviews

We used to waste time debating variable names and minor stylistic choices. Now we have a rule: if it's not covered by our linting tools and doesn't affect functionality or readability, it's probably not worth discussing.

Review Assignment Bottlenecks

Initially, we assigned specific reviewers to each PR. This created bottlenecks when key team members were busy. Now we use GitHub's "request review from team" feature and let anyone jump in.

Ignoring Context

The biggest reviews disasters happened when reviewers didn't understand the larger context of a change. We now require PR descriptions to include:

  • What problem this solves
  • Why this approach was chosen
  • How to test the changes
  • Where this fits in the larger feature (if applicable)

Cultural Change: From Gatekeeping to Collaboration

The real change was cultural, not technical. We started seeing reviews as collaboration instead of gatekeeping. That shift made everything else work.

Reframing the Conversation

We stopped talking about "catching bugs" and started talking about "sharing knowledge." This subtle shift changed how people approached both writing and reviewing code.

Old mindset: "I need to find everything wrong with this code."

New mindset: "How can I help improve this code and learn something myself?"

Making Everyone a Reviewer

Junior developers often feel intimidated about reviewing senior developers' code. We encourage everyone to review everything, with the understanding that questions and learning-focused comments are always welcome.

A junior developer asking "Can you explain why you chose this pattern?" often leads to valuable discussions that help the whole team learn.

Celebrating Good Reviews

In our weekly retrospectives, we highlight examples of particularly helpful code reviews. This reinforces what we value and helps people understand what "good feedback" looks like.

The Results: Why This Process Works

Six months after implementing these changes, our metrics tell the story:

  • Average PR review time: Down from 3.2 days to 4.7 hours
  • Bugs caught in review: Up 40% (small PRs are easier to review thoroughly)
  • Developer satisfaction: Significantly improved (based on quarterly surveys)
  • Review participation: Every team member now actively reviews code

More importantly, code review stopped being a source of friction and became a genuine collaboration tool. Developers actually look forward to getting feedback, and reviewers engage more thoughtfully with the code.

The process isn't perfect, and we're still tweaking it. But it's transformed how our team works together—and that's made all the difference.