DevOps Architecture

[DevOps Architecture] Code Review - PR 300 Lines + 1 Approver + CODEOWNERS

[DevOps Architecture] Code Review - PR 300 Lines + 1 Approver + CODEOWNERS

About this article

As the fifth installment of the “DevOps Architecture” category in the series “Architecture Crash Course for the Generative-AI Era,” this article explains code review.

Review is the final gate of design agreement, not quality assurance. Confusing it with bug-hunting causes the chain of “PRs pile up / one-line-comment approvals / incidents surface in production.” This article handles PR granularity, review viewpoints (the 3 layers of design/implementation/convention), approval rules, and commit conventions as design that doesn’t break even as the team grows.

What is code review in the first place

Think of book proofreading and editing. A different set of eyes reads the author’s manuscript, checking not just typos but also logical gaps and clarity for the reader. Just as writing done alone always has blind spots, code written alone always has oversights.

Code review is the process where another engineer checks code written by a team member before merging, detecting design issues and oversights. GitHub’s Pull Request (PR) is the canonical mechanism for this.

Without code review, design misalignment and latent bugs go unnoticed until they surface in production, ballooning rework costs many times over.

Why code review is needed

Catch design drift before production

Tests verify “does the code work correctly”, but “is this even the right design” can’t be judged by machines. Review is the last gate where humans verify design-decision validity.

Knowledge sharing and preventing single-person dependency

Through reviews, the whole team stays aware of the codebase, preventing areas only one person can touch. It’s the most effective way to lower the bus factor (risk of everything stopping when one person is absent).

Turn implicit quality standards into explicit knowledge

Through review exchanges, the team’s standard for “what counts as good code” gets shared and verbalized.

The 3 layers seen in review

Review is often thought of as “bug-hunting,” but the actual targets split into 3 layers. The starting point of design is not mixing things CI can mechanically guarantee with things only review can detect.

LayerContentWho sees it
Mechanical layerSyntax, types, coverage, Lint, formatCI (humans don’t see)
Code layerReadability, naming, duplication, separation of concerns, simplicityReviewer (main)
Design layerPublic-API stability, architecture consistency, extensibilitySenior, owner

The rule is don’t review things machines handle. Pointing out “Prettier didn’t format” or “spaces unaligned” in review just melts human time - seal that completely with CI and pre-commit. Review focuses only on code layer and design layer - whether you can make this break decides team speed.

PR granularity - smaller is faster

Review time and PR lines are not linear but exponential in degradation. A 300-line PR finishes in 60 minutes, but a 1,000-line PR doesn’t get accuracy even after a full day - empirical, but I’ve never seen exceptions in the field.

xychart-beta
    title "PR lines vs defect-detection rate (estimate)"
    x-axis "PR lines" [100, 300, 500, 1000, 2000]
    y-axis "Defect detection (%)" 0 --> 100
    bar [95, 80, 50, 20, 5]
PR linesRealistic review timeDefect detection rate
~10010-20 minHigh (almost all detected)
100-30030-60 minMid (recommended range)
300-5002 hours-half dayLow (latter half becomes skim-reading)
500+Half day-1 dayExtremely low (almost approval ceremony)
1,000+UnknownAlmost not seen

Google internal research also shows that defect-detection rate plummets the moment you exceed 400 lines. Aim for PRs within 300 lines and split - the front-runner operation. Massive PRs also generate the pressure of “I already submitted, just merge it,” and quality, dev experience, and reviewer psychology all worsen.

PRs within 300 lines. If exceeded, always split or get prior design agreement.

How to split large PRs

It’s said “the feature is large so can’t split,” but in 90% of cases, splitting is possible. Below are typical split patterns.

Split axisExample
Separate structure prep from body1) directory structure / type definitions only → 2) implementation body
Separate refactor from new feature1) tidy existing code → 2) add new feature
Split by layer1) DB schema + migration → 2) API endpoints → 3) UI
Hide with Feature FlagPre-merge with flag off → publish with flag on
Horizontal splitSame change applied to multiple files → split per file group

Putting refactor and new feature in the same PR is a particularly bad choice. Reviewers have to judge “is this change essential or incidental?” line by line, ballooning review time 2-3x. Pass refactor as a standalone PR first, layer the new feature on top - if this order breaks, the team’s overall speed drops.

What to see in review - phased practice

“Review viewpoint checklists” tend to formalize in the field. Practical to vary emphasis by the stage the code is in - “declaring at the start of the review which stage your PR is in” alone greatly changes how reviewers read.

StageWhen this PR isWhat to emphasizeTarget time
1. PrototypeStage of checking whether it worksDesign policy only (operation/naming secondary)15 min
2. ImplementationThe main PR before productionLogic, error handling, tests30-60 min
3. RefactorNo functional changeWhether existing behavior is intact20 min
4. Emergency hotfixIncident responseWhether scope is narrow, easy to roll back10 min

Pointing out “naming is long” or “should split functions” on a prototype PR is stage-mismatched, sparking PR author pushback “that’s not the goal this time.” Conversely, retroactively raising design policy on an implementation PR has large rework, so settle design discussions at stage 1.

Reviewer viewpoint list (front-runner)

Without consciousness, viewpoints to see in review fall into the ritualization of “read, somehow OK.” Below are practical viewpoints with field effectiveness, and don’t see all every time but vary emphasis per PR type - the practical approach.

ViewpointWhat specifically to see
CorrectnessPer spec, edge cases, boundary values (0, 1, null, empty array)
TestsTests present, names that convey intent, how do you notice on failure
ReadabilityNaming, separation of concerns, function length, early return
Error handlingBehavior on failure, logs, user-facing appearance
SecurityAuthorization checks, input validation, SQL injection, secret leaks
PerformanceN+1 queries, cache, useless loops
Backward compatibilityPublic-API changes, DB schema changes, existing-client impact

The minimum line is always seeing the 2 axes of “correctness” and “tests”. Readability and performance are pointed out only when there’s a clear problem, and the trick to keeping review-culture health is not stepping into “the realm of preference.”

Approval rules - how many, by whom

Number and attributes of approvers is a design item that looks small but decides organizational speed. Requiring 2-person approval raises quality, but if person 2 is unmoving for 3 days while person 1 instantly approves, PRs are left for 3 days.

PatternQualitySpeedSuited for
1-person (anyone)MarginalHighSmall / trusted teams
1-person (CODEOWNERS specified)GoodMid-highFront-runner (mid-size)
2-person (1 from CODEOWNERS)ExcellentMidFinance/medical/regulated
2-person (anyone)GoodLowDiscouraged (bottlenecks invisible)

CODEOWNERS (the GitHub feature defining responsibles for specific dirs/files in .github/CODEOWNERS) lets you mechanically enforce “this directory always requires this person’s approval.” Today, 1-person approval + CODEOWNERS required for important areas is the front-runner composition for mid-size teams. 2-person approval looks safe but actually accumulates “review delays as person x person” - excessive design outside regulated industries.

Commit conventions - Conventional Commits

Conventional Commits is the convention of prefixing commit messages with feat: / fix: / refactor: etc. Spread around 2017, today it’s the de facto standard regardless of OSS or SaaS.

prefixMeaning
featNew feature
fixBug fix
refactorCode cleanup without functional change
perfPerformance improvement
docsDocumentation only
testTests only
choreBuild, CI, dependency updates etc.

Typical format is feat(auth): add passkey login flow, of the shape prefix(scope): summary. Putting the BREAKING CHANGE: note in the body becomes the breaking-change flag.

The benefits of Conventional Commits

Adopting Conventional Commits enables release-note auto-generation (semantic-release, release-please) and SemVer auto-decision (fix→patch, feat→minor, BREAKING→major). The side effect “history transforms into a searchable spec” is also strong, and AI’s understanding accuracy when reading change history jumps.

BenefitContent
Release-note auto-generationPick up feat/fix to mechanically generate CHANGELOG.md
SemVer auto-decisionfeat → minor / fix → patch / BREAKING → major
PR filteringExtract only new features with git log --grep='^feat'
AI understanding accuracyStructured history makes AI grasp intent easier

Build semantic-release into CI and auto-tagging and release complete on main merge. Adoption cost is just the first week’s adjustment, after which only benefits remain - the investment.

Squash merge vs preserving history

PR merge methods are 3 - Squash / Rebase / Merge commit - but Squash is the modern front-runner. With 100 fine WIP commits (wip, fix typo, revert, wip2) born on feature branches remaining in main, git blame becomes effectively meaningless.

MethodCharacteristicsRecommended case
SquashCompress all feature commits into one to mainFront-runner (90% of teams)
RebaseLinear merge preserving feature commit structureOSS that wants to retain history
Merge commitLeave feature branch and merge point in historyCombination with Git Flow

In Squash-merge operations, the PR title becomes the commit message as is, so the rule is putting the Conventional Commits prefix in the PR title. PR title feat(auth): add passkey login → same title for the commit on main - this structure has “best chemistry” with release-note auto-generation.

Review pitfalls - collapse of review culture

Review doesn’t function with just structure. The moment the invisible part of review culture collapses, the following antipatterns spread.

PitfallWhy it happens / why it’s bad
LGTM-instant-approval culturePass “didn’t read” with LGTM. Hotbed of incidents
Personal-attack-style reviewComments grilling “why such a way of writing.” Breaks psychological safety, leads to retirement
Style-debate explosionTabs/spaces, semicolons debated every PR. Fully mechanize with Prettier/Biome
Excessively strict approval blockersDemand fixes down to preference range. PRs left for a week
No review-response SLAPR submitted Friday, left until Monday
”Stricter reviews mean higher quality” — excessive blockingPR neglect rots context, actually lowering detection rate
”Fewer comments means a better PR” — instant LGTMHotbed of the “no one actually read it” LGTM-approval culture

Blocking with reason “different from how I write” is a bad choice. Coding style is guaranteed by CI, review focuses only on “will it break or not” - this is the biggest line that keeps team health.

Review SLA - decide response time numerically

Review delays directly kill organizational speed. The lax operation “look when noticed” has the double evil of when PRs are left for 2 days, the writer’s context disappears, dropping review quality too.

SLAResponse timeScope
First review responseWithin 4 hours (business hours)All PRs
Review completionWithin 24 hoursNormal PRs
Emergency hotfixWithin 1 hourPRs with urgent label
Re-reviewSame dayRe-submission after addressing comments

Just clarifying the SLA dramatically resolves the no-one-reviews problem. As support, putting in auto-notifications to Slack/Teams (GitHub’s Pull Request Reviewer feature, pull-reminders bot) and automating “remind after 4 hours” / “re-notify at 24 hours” is the modern rule. Don’t rely on memory for waiting on human reviews - this is an area easy to mechanize and with high organizational-improvement leverage.

Review by AI - current reality

From 2025, AI review has rapidly entered the practical zone. GitHub Copilot Code Review, CodeRabbit, Codium, Graphite Reviewer etc. can now auto-comment on PRs. Today, while “not a replacement for human reviewers,” the field feel is crushing 50-70% of points in the first pass.

Areas where AI review is strongAreas where AI review is weak
Simple bugs, null references, unused variablesDomain-specific business logic
Naming, code conventions, doc gapsArchitecture-consistency / extensibility judgment
Standard security patternsConsistency with past discussions / design agreements
Test gaps, missed boundary values”Is this change even necessary?”

The ideal operation is the division of labor of AI returning all mechanical points first → humans seeing only design and domain logic. Not “AI reviewed so humans unneeded” but “AI does pre-processing so humans can focus on design” - the modern standard composition.

AI decision axes

AI-era favorableAI-era unfavorable
Small PRs + Conventional CommitsMassive PRs + free-form commits
Two-stage AI review + human reviewNo AI review, humans see everything
Divide design judgment with CODEOWNERS”Anyone reviews” operation
Squash merge, history at 1 PR = 1 commitWIP commits scattered in main
Humans focus on design / domain / UXHumans pointing out spaces / naming
  1. Build culture of keeping PR granularity within 300 lines — share splitting techniques
  2. 1-person approval + CODEOWNERS to consolidate design judgment in owners
  3. Conventional Commits and Squash merge to make history automatable
  4. AI-review pre-processing, humans focus on design and domain

What to decide - what is your project’s answer?

For each of the following, try to articulate your project’s answer in 1-2 sentences. Starting work with these vague always invites later questions like “why did we decide this again?”

  • PR-granularity target (within 300 lines recommended)
  • Approval rules (1-person/2-person, presence of CODEOWNERS)
  • Review SLA (first response time, completion time)
  • Commit convention (whether to adopt Conventional Commits)
  • Merge method (Squash / Rebase / Merge commit)
  • Review-viewpoint priorities (line of mechanization)
  • AI-review tool adoption (CodeRabbit, GitHub Copilot Code Review etc.)
  • Style-debate suppression (full mechanization with Prettier/Biome)

Author’s note - “2-person approval mandatory” that killed a startup’s speed

A widely-told case in the industry: a startup adopted “all PRs require 2-person approval,” and at the point members exceeded 10, average merge time exceeded 2 days. When the second reviewer is busy with other work, things stop even if the first has approved. Result: PRs pile up, conflicts increase, rebase hell begins.

This team switched to “1-person approval + CODEOWNERS, only critical directories (payments, auth) require 2-person” - average merge time shortened to half a day. “2-person approval for quality” is the front-runner in regulated industries and core areas of payment systems, but uniform application is a killer of organizational speed. Identifying areas you want to protect quality and laying heavy gear only there - the modern design thinking.

“All PRs 2-person approval” is the slowest design that looks safe.

Summary

This article covered code review, including PR granularity, viewpoints, approval rules, Conventional Commits, Squash merge, and AI-review pre-processing.

Keep PRs within 300 lines, consolidate design judgment via 1-person approval + CODEOWNERS, automate history via Squash + Conventional Commits, AI-review pre-processing. That is the practical answer for code review in 2026.

Next time we’ll cover test design (test pyramid, contract tests, E2E).

Back to series TOC -> ‘Architecture Crash Course for the Generative-AI Era’: How to Read This Book

I hope you’ll read the next article as well.