Code review is one of the highest-leverage practices in software — it catches defects, spreads knowledge across a team, and keeps a codebase coherent. It is also frequently where teams generate friction, delay and resentment. The difference is not tooling; it is a set of habits on both sides of the review, and most of them are about people as much as code.
Good review culture is learned, and it starts with remembering that the goal is better software and a stronger team, not proving who is cleverer.
For the reviewer: be kind and specific
Review the code, not the coder. Comment on the pull request, not the person: "this loop re-queries inside the iteration, which will be slow at scale" lands very differently from "why did you write it this way?" Distinguish clearly between blocking issues (real bugs, security problems) and preferences (style, naming you'd choose differently), and label the latter as optional so the author knows what actually must change.
Ask questions where you are unsure rather than issuing verdicts — the author often has context you lack. And praise genuinely good work; a review that is only criticism trains people to dread the process and hide their changes.
For the author: make review easy
Half of review quality is set before anyone reviews. Keep pull requests small and focused — a five-hundred-line change gets a rubber stamp; a fifty-line one gets real scrutiny. Write a description that explains what changed and why, so the reviewer starts with context instead of reverse-engineering intent. Review your own diff first and clean up the obvious before asking others to spend their time.
When you receive feedback, assume good faith and separate your ego from your code. Not every comment needs a change, but every comment deserves a considered reply — even "good point, but here's the constraint that led to this" keeps the conversation collaborative.
Keeping reviews fast
The silent killer of review culture is latency. A change that waits a day for review blocks the author, invites giant batched pull requests, and grinds delivery to a crawl. Teams that review well treat open reviews as a priority, aiming to respond in hours not days, and use automation — formatters, linters, tests in continuous integration — to handle the mechanical nitpicks so humans discuss things that matter.
Let the machines argue about semicolons and indentation; save human attention for logic, design and edge cases. A team that reviews small changes quickly, kindly and specifically ships faster and builds better software than one that either skips review or turns it into a slow, adversarial gate.
Self-review before requesting anyone else’s time
Reading through one's own diff, as though seeing it for the first time as a stranger would, before ever requesting review from someone else catches an outsized fraction of the trivial issues — a leftover debug log statement, an unused import, an inconsistent naming choice — that would otherwise consume a reviewer's attention and time on problems the author could have caught and fixed alone in under a minute. Teams that build this habit consistently see review comments shift toward genuinely substantive design and correctness questions, since the reviewer's attention is no longer being spent on catching things a careful self-review pass would have already caught first.
Smaller pull requests review faster and more thoroughly, not just more conveniently
A five-hundred-line pull request does not receive ten times the scrutiny a fifty-line one does; in practice it usually receives considerably less thorough attention per line, because a reviewer's genuine, careful attention span for a single sitting is roughly fixed regardless of how much code is placed in front of it, and a large diff exhausts that attention well before reaching the end. Splitting a large piece of work into a sequence of smaller, independently reviewable pull requests is not merely a courtesy to the reviewer's schedule, it produces measurably better review outcomes, since each individual piece receives the kind of close, careful attention only realistically available for a diff a reviewer can hold in their head all at once.
A pull request description is not optional documentation
A description that states what changed and why, including anything a reviewer might otherwise have to guess at — an unusual approach taken deliberately for a reason not obvious from the diff alone, a deliberately incomplete edge case left for a documented follow-up — saves a reviewer from having to reconstruct that same context by inference, or worse, from making an incorrect assumption about intent that leads to a wasted round of clarifying comments. Treating the description as an integral part of the change, not an afterthought filled in hastily after the code is already written, is one of the highest-leverage habits an author can build to make their own reviews faster and less frustrating for everyone involved.
Responding to feedback without treating every comment as a personal referendum
Receiving review well is its own distinct skill from writing reviewable code, and the habit that separates authors who make review pleasant from those who make it exhausting is treating each comment as information about the code rather than as a judgment of the person who wrote it — responding to a genuine disagreement with the actual reasoning behind the original choice, rather than either capitulating immediately without engaging or becoming defensive, keeps the exchange collaborative and is exactly the mirror image of the reviewer-side habit, discussed elsewhere in this cluster of articles, of phrasing comments as questions rather than verdicts in the first place.
Marking a pull request explicitly as a draft or work-in-progress
Requesting early, informal feedback on a not-yet-finished approach is genuinely valuable, and it works considerably better when the pull request is explicitly marked as a draft rather than presented as finished, since a reviewer looking at what they believe is a completed change will naturally scrutinize it far more thoroughly, and possibly more critically, than the author actually wanted at that early stage — explicitly signaling draft status sets the right expectation on both sides, inviting high-level, directional feedback rather than the fine-grained, ready-to-merge-level review that would otherwise be a mismatch for work still very much in flux.
Why a rebased history is easier for a reviewer than a series of "fix typo" commits
A pull request whose individual commits each represent a coherent, logical step — rather than an unfiltered chronological log of every save point, half of them just fixing something the previous commit broke — lets a reviewer follow the actual reasoning behind a change commit by commit, which is a genuinely different and often easier reading experience than facing one enormous, undifferentiated diff all at once; cleaning up commit history with an interactive rebase before requesting review, squashing away the "fix typo" and "oops forgot this file" commits, is a small extra step that measurably improves how easy the resulting change actually is to review.
Responding to every comment, even the ones simply being acknowledged and accepted
Silently applying a suggested change without any reply at all leaves a reviewer uncertain whether the suggestion was seen, agreed with, or simply missed entirely, and the small habit of replying "done" or "good point, fixed" to every comment, even ones requiring no further discussion, closes that loop explicitly and lets a reviewer scan the resulting thread and see, at a glance, that every point raised was actually addressed rather than having to re-diff the whole change to check for themselves.
Flagging deliberately out-of-scope issues instead of silently fixing them
Noticing an unrelated problem while working on a change is common, and fixing it inline within the same pull request, however well-intentioned, tends to make the diff harder to review by mixing two unrelated concerns together — noting it explicitly instead, either as a comment or a quickly filed follow-up issue, keeps the current change focused and reviewable while still ensuring the unrelated problem does not simply get forgotten the moment it was noticed.
Linking related context directly in the description rather than assuming familiarity
A pull request that references 'the issue we discussed' or 'the approach from last week's design doc' without a direct link forces a reviewer to either already have that exact context in mind or to go hunting for it separately — linking the relevant ticket, prior discussion, or design document directly in the description removes that friction entirely, and is a small habit that compounds significantly for a reviewer coming to a change without the same background the author has been living in for days.
Why re-requesting review after addressing feedback should highlight what changed
Pushing a fix and silently re-requesting review forces the reviewer to re-scan the entire diff to figure out what actually changed since their last pass, when a short comment pointing directly at what was addressed — 'updated the validation per your comment, see the change in `validate.ts`' — lets them jump straight to verifying the fix rather than re-deriving what changed from scratch, a small courtesy that measurably speeds up the second round of review.
Why including a screenshot or short recording changes a UI-facing review's speed
A pull request that changes visible behavior but includes no screenshot or short screen recording forces a reviewer to either check out the branch and run it locally just to see the result, or approve based purely on reading code and imagining the outcome — attaching a quick before-and-after screenshot or clip directly in the description removes that entire step, letting a reviewer confirm the visible result matches what was intended in seconds rather than needing to reproduce the environment themselves.
Why explicitly stating what was NOT tested is as useful as stating what was
A description that lists what was verified manually, and just as importantly what was deliberately left unverified due to time constraints or a known limitation, gives a reviewer an accurate picture of the change's actual coverage rather than an implicit assumption that everything not mentioned was thoroughly checked — omitting this is not dishonest, but it does leave a reviewer to either assume full coverage incorrectly or ask directly, both of which cost more time than simply stating it upfront.
Why an author should read their own diff on the review platform, not just in the editor
Code that looks clean and obvious in a familiar editor can read very differently in a plain diff view, where surrounding context is more limited and syntax highlighting is often less rich — checking the actual rendered diff on the review platform itself, the exact view the reviewer will see, before requesting review catches presentation issues an editor's more forgiving view would never reveal.
Why an author should anticipate the reviewer's most likely question in advance
Thinking through, before requesting review, what a careful reviewer is most likely to ask — why this approach over an obvious alternative, what happens on a particular edge case — and answering it directly in the description saves a full round trip of question and answer, and often reveals to the author, while writing that anticipated answer, a gap in their own reasoning they had not yet noticed themselves.