PRACTICAL GUIDE · GITHUB CODE REVIEW
GitHub pull-request reviewer assignment: practical options and trade-offs
Who should review this pull request? If your team keeps asking, it helps to know what GitHub can handle and when you need something more. Here are five approaches, from manual requests to a dedicated routing tool.
Disclosure: I build TriagePilot, one of the options discussed here. The feature descriptions come from the documentation linked below. The examples are made up to illustrate the choices; they aren’t customer results.
Work out why reviews are waiting
Before choosing a tool, agree on three things: who knows the code, who has time to review it, and whose approval you need before merging. Each may need a different solution.
Look through a few recent pull requests that waited for review. Who was asked? Did they pass the request to someone else? Were they away, overloaded, or unsure why they’d been chosen? If nobody knows who owns a directory, agree on an owner first. If the owner is on holiday, decide who should cover.
A review request sends a notification. Required approvals and checks, configured in GitHub, determine whether a pull request can merge. Asking three people to review does not mean all three must approve. Decide who to ask and what should block a merge separately.
1. Manual reviewer requests
Choosing reviewers by hand works well when authors know whom to ask. They can explain a change and check when a specialist has time. They may also know something a file-path rule would miss, such as who took part in an earlier design discussion.
The trouble is that new contributors don’t have that knowledge yet. They may ask the same familiar specialist, even when someone else has time. A shared ownership list or a simple review rotation can help.
If this takes little effort, keep doing it. Consider another approach when authors regularly struggle to find an owner, chase someone who is away, or rely on a team lead to hand out every review.
2. CODEOWNERS: assign owners to paths
A CODEOWNERS file maps repository paths to GitHub users or teams. For a non-draft pull request, GitHub requests the relevant owners; drafts trigger those requests when marked ready for review. The file used comes from the pull request’s base branch. See GitHub’s CODEOWNERS documentation.
This example belongs in .github/CODEOWNERS. Replace the invented organization and teams with real, visible teams that have write access:
# Example only: later matching patterns take precedence.
* @example-org/maintainers
/src/payments/ @example-org/payments
/.github/CODEOWNERS @example-org/maintainersCODEOWNERS gives contributors a place to look up ownership, and the team can review changes to it like any other code. It does not choose the least busy person or track planned absences. Requiring owner approval is a separate branch-protection or ruleset decision; simply committing the file does not require approvals. Where multiple owners share a pattern, the owner-review requirement does not mean every listed owner must approve.
Use it when directory ownership is stable and requests to those owners are enough. Review the file as responsibilities change. Protect ownership-policy changes with appropriate review, and avoid assuming that TriagePilot imports this file: its ownership configuration is separate.
3. Native team auto-assignment
If a GitHub team owns the code, GitHub’s built-in auto-assignment may be enough. It selects a configured number of members when that team is requested. GitHub documents availability for public organization repositories and private organization repositories on the applicable paid plans in its team code-review settings guide.
Round robin favors the member whose last request was longest ago; outstanding work does not drive that rotation. Load balance uses recent request totals and outstanding reviews, aiming for an even distribution over 30 days. A request count won’t tell you how much work a review takes, so neither algorithm can guarantee an equal share of the effort.
Members with Busy status are excluded. If everyone is Busy, the request stays with the team. That helps when someone is unavailable, though it doesn’t let you schedule an absence. Your team still needs to agree on when to set and clear Busy status.
Settings also allow permanent member exclusions, inclusion of child-team members, and counting existing requests. Check how team requests interact with required code-owner review before rollout. If path ownership, assigning a few team members, balancing requests, and skipping Busy members cover your needs, start here. You may not need another service to run.
Compare the options
The table shows what each approach handles and what you’ll need to maintain. Custom automation and dedicated tools vary, so check the details of any tool you’re considering.
On small screens, scroll the table horizontally. You can also focus the table region and use the arrow keys.
| Approach | Ownership | Workload | Availability | Risk policy | Maintenance | How to try it |
|---|---|---|---|---|---|---|
| Manual requests | Author’s knowledge | Team coordination | Ask directly | Human judgment | Shared knowledge and rotation | Discuss choices before requesting |
| CODEOWNERS | Path-to-owner map | No balancing itself | No schedule itself | Owner approval configured separately | Keep paths and owners current | Inspect syntax and test in a repository |
| Native team assignment | Requested team | Round robin or load balance | Busy exclusion | Separate merge requirements | Team membership and settings | Test team requests before broad rollout |
| Custom automation | Whatever you implement | Whatever you implement | Chosen data source | Custom logic and checks | Your code, permissions, retries | Build a read-only simulation |
| Dedicated routing tools | Product-specific rules | Verify each product | Verify signals and scheduling | Verify routing versus enforcement | Configuration plus service operation | Check for a mode that makes no GitHub changes |
4. Custom automation
A script, GitHub Action, or GitHub App can handle rules that native settings don’t support. This can work well for a specific requirement, provided someone on the team can maintain it. Write down what information it needs and which reviewers it should choose before building it.
Getting the first request to work is only the start. Decide what happens when events repeat, the pull-request head changes, permissions change, or GitHub accepts a request before your app saves the result. Keep secrets out of repository configuration, limit what the automation can change, and make sure someone can investigate and recover from failures.
Add a way to preview reviewer choices before sending requests. Test typical changes, owners who are away, and cases where no reviewer is eligible. Before committing to custom automation, make sure someone can maintain it after the original author moves on.
An example: the payments specialist is away
Imagine eight developers maintaining a service. A documentation correction and a payment-authorization change both touch owned paths. The team wants one human review for ordinary changes and two for its high-risk cases. Its payments specialist will be away from Monday morning until Thursday afternoon.
Who can review a payments change, and who will be available when it opens? How many approvals should it need? Native team assignment can spread requests across members, but the team also wants the review count to depend on risk and absences to start and end at set times.
Now suppose the specialist was requested on Friday and hasn’t reviewed it by Monday. Should the system replace that request? What if the specialist already approved? What if every eligible alternative is absent? Write those cases down; “availability aware” is too vague to specify the result.
Answering those questions gives you concrete cases to test. If your team doesn’t need these rules, CODEOWNERS and native settings may be enough.
5. Dedicated routing tools, including TriagePilot
Consider a dedicated tool when you need to combine ownership, workload, and availability to choose reviewers—and see why they were chosen. Check what data it uses, what it changes in GitHub, and what happens when no suitable reviewer is available. Tools differ on these details.
TriagePilot is a self-hosted, Fair Source GitHub application. It evaluates pull-request changes against rules you set in .triagepilot.yml. You can give sensitive paths such as src/auth/** more weight, set size limits that mark large changes as high risk, and cap the risk score for documentation-only changes. Those rules determine the risk tier used to decide how many human reviewers to request.
The same configuration file maps paths to code owners, so you can define both how risky a change is and who should review it. Reviewers must be individual GitHub handles; organization teams aren’t supported. See the repository configuration reference for the available rules.
TriagePilot requests no human reviewer for low-risk changes, one for medium-risk changes, and one by default for high-risk changes. You can configure high-risk changes to request up to two. Matching owners are preferred; configured fallback reviewers can fill remaining slots. The author is excluded. If there aren’t enough eligible reviewers, it records the shortfall.
Absences are scheduled centrally by an administrator, outside repository YAML. They narrow eligibility for new decisions and can trigger replacement of outstanding reviewers under the documented policy. An effective approval is preserved. TriagePilot does not expand the original eligible pool or lower the required count when no replacement is available. See the availability reference.
Reviewer selection remains distinct from approval enforcement. In enforce mode, the human-review policy can be made a required check through a GitHub ruleset configured by the operator. The selected reviewers are suggestions: active approvals from individual people count, even if they weren’t selected. Read the policy reference before changing merge requirements.
Evaluate TriagePilot in shadow mode
Start with one representative repository and keep mode: shadow. TriagePilot reads GitHub data and saves its decisions locally. It sends no reviewer requests and writes no labels or checks. You’ll still need to set up and run the application, database, and GitHub App to try it.
Try routine changes, sensitive paths, owners who are away, and changes with few eligible reviewers. Check the recorded risk level, reviewer choices, and explanations against what your team expects. Note where you disagree and adjust the configuration before testing again.
Consider enforce mode once you’re happy with the sample and have checked the permissions and merge requirements. TriagePilot reads the mode from the trusted base revision, so an unmerged pull request cannot enable its own writes. Follow the rollout guide linked below when you’re ready to switch.
Sources and review scope
GitHub behavior was checked against its official documentation on the reviewed date. Product descriptions were checked against the v1.1.1 release documentation linked above. Recheck these sources when upgrading or changing policy: