Chapter 9: Code Review

seg process code-review engineering-culture collaboration

Status: Notes complete


Overview

Code review is the process by which code is examined before being submitted to a codebase. At Google, code review is not merely a correctness gate — it is a cultural institution that enforces standards, distributes knowledge, creates accountability, and builds shared ownership across a codebase that serves thousands of engineers and billions of users.

Chapter 9 examines code review as a systemic practice rather than an individual habit. The authors argue that code review’s value is not primarily in catching bugs (though it does that) — it is in creating a sustainable, legible, and consistent codebase over time. They analyze the mechanics of Google’s review process, the distinct types of approvals required, the categories of review a change may fall into, and the anti-patterns that erode code review’s value when the process is poorly implemented.

The chapter also confronts a tension inherent in code review: it adds friction to software development. The authors accept this trade-off explicitly. The friction of review is worth the benefits of a codebase that remains comprehensible and maintainable at scale. The key is to make code review efficient — minimizing unnecessary friction while preserving the friction that produces real value.


Core Concepts

Change List (CL): Google’s term for a code change submitted for review, roughly equivalent to a pull request. A CL is the unit of change that flows through the review process.

LGTM (Looks Good To Me): An approval signal in Google’s code review system, indicating that a reviewer is satisfied with a CL. Google requires multiple LGTMs from specific categories of approver before a CL can be submitted.

Readability approval: A specialized approval granted only by engineers who have passed Google’s language-specific readability process — a formal certification that an engineer understands idiomatic style for a given language. Readability approval ensures new code follows Google’s language conventions.

Code ownership: In Google’s system, every piece of code has designated owners — engineers responsible for the quality and health of that code. Owner approval is required before a CL touching their code can be submitted.

Green state: The requirement that the codebase always remains in a passing state. No CL should be submitted that breaks existing tests or degrades the codebase.


How Code Review Works at Google

Google’s code review process is built around a tool called Critique (the internal review tool), but the process itself is the more important subject. A CL goes through the following lifecycle:

The Review Flow

  1. Author creates a CL: The engineer writes a change, runs existing tests locally, and writes a clear CL description explaining what the change does and why.
  2. Automated checks run: Presubmit checks (linters, formatters, automated test suites) run before human reviewers are engaged. These catch mechanical issues without consuming reviewer time.
  3. Author selects reviewers: The author chooses reviewers, typically one or two people familiar with the code. The system may also suggest reviewers based on code ownership.
  4. Reviewers examine the change: Reviewers read the code, leave inline comments, and either approve (LGTM) or request changes.
  5. Author addresses feedback: The author responds to comments — either making the requested change, explaining why they disagree, or asking for clarification.
  6. Iteration continues: The cycle of comment and response continues until the reviewers are satisfied.
  7. Final approvals granted: The CL collects the required approvals (see the three-approval system below).
  8. CL is submitted: The change is merged into the codebase.

The Three Approval Gates

Google requires three distinct approvals before a CL can be submitted. These three gates serve different purposes and cannot substitute for one another:

Approval TypeWho Can Grant ItWhat It Verifies
LGTM (correctness)Any reviewer familiar with the codeThe change is correct, well-designed, and does what it claims
Owner approvalA designated owner of the affected codeThe change is appropriate for this codebase and consistent with its direction
Readability approvalAn engineer certified in the language’s readability processThe change follows Google’s idiomatic style for the language

In some cases a single reviewer may satisfy multiple approval gates (e.g., a code owner who also has readability certification). In other cases, three separate people are required. The three-gate system exists because each type of review requires different expertise and serves a different quality function.

Why three separate gates?

  • A brilliant engineer may write a correct, well-designed change that is stylistically inconsistent with the codebase — readability review catches this.
  • A readability-certified engineer may approve clean code that is architecturally wrong for the module — owner review catches this.
  • A code owner may approve a change out of familiarity without scrutinizing its correctness — LGTM review catches this.

The separation of concerns at the approval level mirrors good software design: each gate checks exactly one class of property, and the combination of gates provides comprehensive coverage.


Benefits of Code Review

The authors identify six distinct categories of benefit from code review. It is important that these benefits are cumulative — code review is not justified by any single benefit alone but by the compound value they produce together.

1. Code Correctness

The most obvious benefit: a second pair of eyes catches bugs, logic errors, and edge cases the author missed. The authors are careful to note that code review is not a substitute for testing — automated tests provide stronger correctness guarantees for a broader range of inputs. Rather, code review catches the bugs that tests don’t: incorrect assumptions, missing error handling, subtle logic errors that pass existing tests, and design flaws that make future bugs more likely.

2. Comprehension and Legibility

A reviewer who must understand code in order to review it is a proxy for future readers of that code. If a reviewer cannot understand what a function does, neither can the engineer who inherits the code in two years. Code review forces authors to write code that is legible to someone other than themselves.

This benefit is often undervalued. Much code is written by engineers who understand it deeply and will never need to re-read it. Code review introduces a reader with fresh eyes, surfacing assumptions, missing documentation, and naming choices that seemed obvious to the author but are opaque to others.

3. Code Consistency

Consistency — in naming conventions, error handling patterns, API design, and code structure — is a property of a codebase, not of individual files. A single engineer may write beautifully consistent code; a thousand engineers working independently will produce a patchwork of styles unless review enforces norms.

Google’s readability process and readability approval gate exist specifically to enforce consistency. An engineer with readability certification knows what idiomatic Go, Java, or C++ looks like at Google, and they will flag deviations from that idiom even when the deviation is technically correct.

4. Psychological and Cultural Benefits

Code review creates psychological safety around code quality: authors know their code will be reviewed, which raises their bar before submission. The expectation of review creates a culture where writing clean, readable, well-commented code is the norm, not a favor to future maintainers.

Code review also distributes code ownership psychologically: when a reviewer approves a change, they share responsibility for that code. This creates accountability without creating bottlenecks — multiple engineers are invested in the quality of any given piece of code.

5. Knowledge Sharing

Code review is a passive but powerful knowledge distribution mechanism. Reviewers learn about parts of the codebase they might not otherwise encounter. Authors learn about patterns, libraries, and idioms they were unaware of through reviewer suggestions. Over time, code review reduces the concentration of knowledge in individuals and spreads it across the team.

This benefit compounds over time. In a mature engineering culture, code review is one of the primary channels through which junior engineers learn the codebase, the team’s coding standards, and the reasoning behind architectural decisions.

6. Opening Up Auditing

Every change that goes through code review has a permanent record: who wrote it, who reviewed it, what was discussed, and what was changed in response to feedback. This audit trail has practical value for debugging (“who introduced this behavior and why?”), compliance, and organizational learning.


Code Review Best Practices

Be Polite and Professional

Code review feedback must be directed at the code, not the author. The difference between “this function is wrong” and “this design won’t work because X” is significant — the latter explains the problem and implicitly invites a solution. Comments like “obviously wrong” or “this is terrible” are never acceptable.

The golden rule: Code review comments are about making the code better, not about demonstrating the reviewer’s superiority. Reviewers should ask questions rather than make accusations; authors should assume good intent in reviewer comments.

Authors also have an obligation to respond professionally. Disagreeing with a review comment is acceptable and sometimes right — but disagreement must be expressed with reasoning, not frustration. If author and reviewer cannot agree, the issue should be escalated rather than allowed to fester.

Write Small CLs

The single most impactful practice for efficient code review is keeping CLs small. The relationship between CL size and review quality is roughly inverse: very large CLs receive superficial reviews because reviewers cannot hold the entire change in working memory at once. Small CLs receive thorough reviews because reviewers can reason about the entire change.

Google’s guidance: a CL should do one thing. If it does two things that are separable, it should be two CLs. If it is large because it is implementing a large feature, it should be broken into a series of stacked CLs, each of which leaves the codebase in a working state.

Benefits of small CLs:

  • Reviewers can complete reviews quickly, reducing author wait time
  • Bugs introduced in small CLs are easier to identify and revert
  • The change history remains navigable

Write Good CL Descriptions

A CL description is not a commit message in the minimalist tradition (“Fix bug”). It is a document that explains:

  • What the change does (briefly, in the first line — this becomes the commit headline)
  • Why the change was made (what problem it solves, what requirement it satisfies)
  • How the design decisions in the change were made (when non-obvious)

A good CL description allows a reviewer to orient themselves before reading the code, and allows a future engineer to understand the intent of the change when they encounter it in git history.

Keep Reviewers to a Minimum

Larger reviewer lists produce worse reviews. When many people are asked to review, each individual reviewer experiences diffusion of responsibility — assuming others will catch any issues they miss. The result is multiple superficial reviews rather than one thorough review.

Google’s guidance: one or two reviewers is almost always sufficient. Exceptions include CLs touching security-sensitive code (where a security reviewer may be required), CLs with broad cross-team impact, or CLs requiring specialized domain expertise.

Automate Where Possible

Any check that can be automated should be. Style enforcement, import ordering, dead code detection, test coverage thresholds — these should all be run by automated tools before human reviewers see the code. Human reviewers are expensive, slow, and subject to inconsistency. Automated tools are fast, cheap, and perfectly consistent.

The practical implication: if a reviewer finds themselves leaving the same style comment repeatedly, that is a signal that the check should be automated. The reviewer’s job is to apply judgment; anything that does not require judgment should not require a reviewer.


Types of Code Reviews

Different categories of change require different review emphases. The authors identify four main types:

Greenfield Reviews

A greenfield review examines code for a new project or a new major feature — code that has no predecessors and no existing patterns to conform to. Greenfield reviews are the most demanding because:

  • There are no existing idioms to compare against
  • The design decisions are being made for the first time
  • Mistakes made here will propagate through all future code that builds on this foundation

Greenfield reviews should be treated as design reviews as much as code reviews. They benefit from involving senior engineers and owners early, before significant implementation work is committed.

Behavioral Changes

A behavioral change CL modifies what existing code does — altering logic, changing an API, modifying data transformations. These reviews focus primarily on:

  • Correctness: Does the change do what the CL description says?
  • Test coverage: Are there tests that verify the new behavior? Are old tests updated to reflect it?
  • Impact analysis: What other code may be affected by this behavioral change?

Behavioral changes are the most common type of CL and the type most likely to introduce bugs. Reviewers should be skeptical and thorough.

Bug Fixes and Rollbacks

Bug fix CLs require careful review to verify that the fix addresses the root cause, not just a symptom. A common mistake is a fix that makes the bug less visible without eliminating it. Reviewers should ask: “Does this fix prevent the condition that caused the bug, or does it handle the bug’s effects?”

Rollback CLs — which revert a previous change — deserve equally careful review. Rollbacks are often done under time pressure after an incident, but a poorly considered rollback can reintroduce bugs that the reverted change was fixing.

Refactorings and Large-Scale Changes

Refactoring CLs (restructuring code without changing behavior) should in principle be easy to review — if behavior doesn’t change, the tests should continue to pass. In practice, refactorings can be difficult to review because they touch large amounts of code simultaneously, making it hard to verify that no behavioral changes crept in.

Best practices for refactoring reviews:

  • Keep refactoring and behavioral changes in separate CLs
  • Rely heavily on the test suite — if tests pass before and after, the refactoring is likely safe
  • Use automated refactoring tools where available to reduce human error

Large-scale changes (LSCs) are a special category at Google: automated changes made across tens of thousands of files simultaneously (e.g., updating a deprecated API across the entire codebase). LSCs have their own infrastructure (the Rosie system) and review process, because the scale makes individual CL review impractical.


Anti-patterns in Code Review

Rubber-stamping

Approving a CL without actually reading it — giving LGTM because the author is trusted, because the reviewer is busy, or because the CL looks big and daunting. Rubber-stamping defeats the purpose of review entirely. It creates a false sense of oversight while providing none of the actual benefits.

Nitpicking on Style

Leaving a series of minor style comments on a CL while missing substantive design or correctness issues. Style enforcement should be automated; a reviewer spending time on style is a reviewer not spending time on design. If style comments appear in a review, they should be framed as suggestions (“nit:”) rather than blockers.

Blocking on Opinion

A reviewer who blocks submission of a correct, well-designed CL because they would have made a different (but equally valid) implementation choice is abusing the review process. Code review is not a veto mechanism for stylistic preferences. If a change is correct and consistent, it should be approved even if the reviewer would have done it differently.

Requiring Large CLs

A reviewer who asks an author to combine a series of small, clean CLs into a single large CL because it would be “easier to review together” is wrong. The opposite is true. Large CLs are harder to review, more likely to contain bugs, and harder to revert if they cause problems.

Over-reviewing

Requiring more reviewers than necessary, or requiring approval from reviewers who don’t have specific expertise in the affected code, adds friction without adding quality. Every unnecessary review gate is time taken from both the author and the reviewer.


TL;DRs

  • Code review has many benefits, including ensuring the code is correct, comprehensible, and consistent; enforcing engineering standards; and enabling knowledge sharing.
  • Always check your code before sending it out for review.
  • Provide context and motivation in the code review and in the CL description.
  • Code review should be efficient. Keep changes small and focused to make reviews efficient and productive.
  • As a reviewer, prioritize important issues over style nitpicking.
  • Provide constructive feedback and avoid conflict.
  • Automate everything you can so that reviewers are never wasting time on things that don’t require judgment.
  • Respond to comments and don’t disappear — keep the review moving forward.
  • Consensus should be attempted before escalating disagreements.

Key Takeaways

  1. Code review at Google requires three separate approval gates — correctness (LGTM), ownership, and readability — each checking a distinct quality property that the others cannot substitute for.
  2. Code review’s primary value is not bug detection but the compound effect of enforced consistency, distributed knowledge, psychological accountability, and a permanent audit trail.
  3. Small CLs are the single most impactful code review practice: they enable thorough review, easier rollback, and navigable change history.
  4. Automate everything that does not require human judgment — style, formatting, lint, and coverage checks should never consume a human reviewer’s time.
  5. CL descriptions are first-class artifacts: a good description explains what, why, and how — allowing reviewers to orient themselves and future engineers to understand the change’s intent.
  6. Different types of CLs require different review emphases: greenfield reviews are design reviews; behavioral changes require correctness scrutiny; refactorings rely on the test suite; LSCs require specialized infrastructure.
  7. Rubber-stamping is the most dangerous anti-pattern: it creates the appearance of oversight while providing none of the actual quality guarantees that code review is meant to supply.
  8. Reviewers must prioritize correctness and design over style: style disagreements should be automated or flagged as non-blocking suggestions, not treated as reasons to block submission.
  9. Code review builds a culture of collective ownership: when reviewers share responsibility for what they approve, the entire team’s investment in code quality increases.
  10. The cost of code review friction is a deliberate trade-off: the authors accept that review adds latency to development in exchange for a codebase that remains comprehensible and maintainable at Google’s scale over time.

  • ch10-documentation — Parallel chapter on written artifacts; documentation and code review share the theme of making knowledge legible and durable
  • ch19-critique — Google’s internal code review tool, Critique, discussed in depth in the tooling section
  • DDIA Chapter 1 — Maintainability as a system property; code review is one of the primary mechanisms that produces maintainable code
  • FSA Chapter 5 — Architecture fitness functions as an automated complement to code review for architectural properties

Last Updated: 2026-06-02