Code review is the highest-bandwidth teaching channel most teams possess, and also their most reliable generator of quiet resentment. The same mechanism that spreads knowledge, catches bugs and keeps a codebase coherent can, badly run, become a bottleneck where pull requests age like unpaid invoices and feedback lands like verdicts. The difference between the two outcomes is not tooling. It is a handful of habits, split evenly between the two sides of the diff.
Worth stating first what review is for — because teams that never agree on this fight forever. Review exists to catch defects a second brain can see, to spread knowledge of the change through the team, and to keep the codebase consistent enough that anyone can work anywhere. It is not a gate for proving cleverness, a style tribunal, or a substitute for automated checks.
The author's half: make reviewing cheap
Review quality is decided mostly before the review starts, by the shape of what is submitted. Small changes get good reviews; enormous ones get skimmed and rubber-stamped — reviewer attention collapses as the diff grows, which means the riskiest PRs systematically get the weakest scrutiny. Splitting work into reviewable slices is therefore not bureaucracy; it is how you purchase real review at all.
The description is the second purchase. State what the change does, why now, how you tested it, and where you yourself are unsure — that last line is the most underused sentence in engineering, and it aims the reviewer's attention exactly where it pays. Walk your own diff before requesting review and annotate the surprising parts; every question you pre-empt is a round trip saved. And let machines do the machine work: formatters and linters in CI mean no human ever spends attention on indentation again.
The reviewer's half: comment on the code, decide with judgement
The reviewer's first discipline is tone mechanics. Comment on the code, never the coder — 'this function re-reads the file per loop iteration' rather than 'you always do this'. Ask questions where you might be missing context: 'what happens if this list is empty?' both catches the bug and respects the possibility that it is handled elsewhere. Prefix the optional with 'nit:' so nobody mistakes taste for blockers — and when a whole thread is taste, say so and let it go. Consistency arguments belong in the style guide, once, not in every review.
The second discipline is judgement about severity. Block on correctness, security, data loss, irreversible mistakes. Approve with comments for everything a follow-up can fix. The reviewer who blocks a working fix over a variable name is spending the team's trust budget on decoration — and trust is the currency that makes authors submit early, rough and honest instead of late, polished and defensive. Speed is part of quality too: a review that arrives in hours keeps the author's context warm; one that arrives in four days reviews code the author has already forgotten.
What compounds
Run this way, review compounds. Juniors absorb the codebase's idioms PR by PR; seniors discover what is actually being built at the edges; bugs die in the cheapest phase of their lifecycle; and the written trail of questions and answers becomes documentation no one had to schedule. The team's shared standard rises without a single meeting about standards.
The test of a healthy review culture is simple and brutal: do people submit their work early and unsure, or late and defended? Where review is a conversation between colleagues staring at the same problem, you get the first. Where it is a performance graded by a judge, you get the second — and the bugs ship inside the armour. Choose the conversation, one comment at a time.