Short answer
Separate the blocking from the optional, and attach a reason to every request. "This needs to change because it breaks on empty input" lands; "why did you do it this way?" reads as an accusation even when it is a genuine question. Text has no tone, so the reason has to carry it.
Code review is where most engineering teams have their conflict, and almost none of it is really about the code. It is about status, tone and the fact that written feedback strips out every softening signal that would exist in conversation.
The Negativity Bias of Text
Written communication is systematically read more negatively than it was intended. A neutral comment reads as mildly critical; a mildly critical comment reads as hostile. Reviewers calibrate tone against what they meant, while authors calibrate against what they read - which is why "just curious, why not use a map here?" can start an argument.
Mark what is blocking and what is not
The single highest-return change any team can make to its review culture is labelling severity, because most review friction comes from authors not knowing which comments they are allowed to decline.
- blocking: this must change before merge, and here is the specific reason.
- suggestion: I think this would be better, your call.
- nit: cosmetic, feel free to ignore.
- question: I genuinely do not understand this, and I am not implying anything by asking.
Prefixes look bureaucratic for about a week and then quietly remove most of the friction, because the author stops having to guess at intent.
Attach the reason, always
A request without a reason is an assertion of authority, and people push back on authority far more than on reasoning.
- Instead of "don't do it this way" → try "this will allocate on every request - can we hoist it out of the loop?"
- Instead of "why did you write it like this?" → try "what was the reason for the manual retry here? If it's the timeout case, the client already handles that."
- Instead of "this is wrong" → try "this breaks when the list is empty - line 40 will index into nothing."
Review the code, never the person
"You always forget to handle nulls" is a performance conversation happening in the wrong venue, in public, in writing. If you have a pattern concern about someone's work, that belongs in a 1:1 with their manager or directly with them - not annotated onto a pull request where the audience is the whole team.
If you are the author
Assume good intent even when the phrasing does not support it - most terse reviewers are busy rather than hostile. If a comment genuinely reads as an attack, move it out of text: "Happy to change this - can we grab five minutes? I want to make sure I understand the concern properly." Almost every review conflict dissolves the moment it becomes a conversation, because tone returns.
When the review has already gone badly
If a thread has turned into an argument, stop replying in the thread. The reply-count spiral is visible to the whole team and neither party can back down gracefully in public. Say "let's take this offline" and mean it, then resolve it in a call and post a one-line summary of what you agreed. The summary matters - it shows the team that disagreement gets resolved rather than won.
Frequently asked questions
How do you give code review feedback without sounding rude?
Attach a reason to every request and label whether it blocks the merge. "Blocking: this breaks on empty input at line 40" is clearly about the code; "why did you do this?" reads as an accusation because text carries no tone to soften it.
What do you do when someone takes code review feedback personally?
Move it out of writing. A short call resolves almost every review conflict because tone and intent become audible again. Continuing to reply in the thread escalates it in front of the whole team and leaves neither person a graceful exit.
Should code review comments be blocking or suggestions?
Both, but say which. Most review friction comes from authors not knowing whether they are allowed to decline a comment. Prefixes like blocking, suggestion and nit remove that ambiguity almost entirely.
How do I handle repeated quality problems in someone's pull requests?
Not in the pull request. A pattern across multiple reviews is a performance conversation, and holding it in public annotations is both ineffective and humiliating. Raise it privately, with specific examples, in a 1:1.