Reviewing without starting a fight
Comments land badly when they read as verdicts on the person instead of facts about the code. The ones that get taken carry their reason with them, and the only thing worth blocking a merge over is a change that leaves the system worse than it found it.
Think of two notes left on a colleague's desk. One says the code is wrong. The other says that if two requests arrive together this counter loses one, and asks whether that is handled somewhere. Both spotted the same bug; only one gets fixed today.
Review is where most engineering disagreements actually happen, and it is the worst available room for having them: asynchronous, written, permanent, and watched by the rest of the team. The comments that turn into arguments are rarely the ones that were harshest. They are the ones that gave the author nothing to do except agree or defend themselves.
The question people arrive with is not how to be nicer. It is that a review went badly last week, both sides were technically right about something, and the change took four days and a private message to land.
What the review is for#
Google’s published standard for code review is one sentence long, and most review conflict is a disagreement with it rather than with a colleague. Reviewers should favour approving a change once it is in a state where it definitely improves the overall code health of the system being worked on, even if the change is not perfect. The reasoning is given directly underneath: there is no such thing as perfect code, only better code, and what a reviewer should be seeking is continuous improvement rather than perfection.
Read that as an instruction about scope and a lot of friction disappears. The comparison is not between this change and the change you would have written. It is between the codebase with this change and the codebase without it. A reviewer who is holding out for their own version is running a different process, and the author can feel that they are, which is why the thread gets tense before anybody has said anything rude.
The same standard sets the counterweight, so this is not an argument for waving things through: reviewers should balance the need to make forward progress against the importance of the changes they are suggesting. Some suggestions are worth the delay. The skill is being able to say which, out loud, in the comment itself.
The comment that lands#
The first rule in Google’s guidance on writing review comments is a grammatical one with an outsized effect: always make comments about the code, never about the developer. It sounds like an etiquette note and it is really about actionability. “You have not thought about concurrency here” cannot be verified, cannot be tested, and leaves the author only the choice of accepting a characterisation or arguing with it. “If a second request arrives before this one commits, both read the same balance” names a case. The author can go and check. Either they find it or they find why it cannot happen, and both outcomes are progress that costs nobody anything.
The second is to explain your reasoning — to say why, not only what. A bare instruction asks for compliance and gets either compliance or resistance, and neither teaches anybody anything. A reason can be examined, which means it can also be shown to be wrong, which is the property that keeps a review from turning into a ranking of the two people in it.
The third is the balance between pointing out problems and giving direct guidance. The guidance is explicit that it is generally the developer’s responsibility to fix a change, not the reviewer’s — a reviewer is not obliged to design the solution. Handing over a finished rewrite feels generous and quietly changes the subject: the thread is now about your code, in someone else’s branch, and disagreeing with it costs the author more than disagreeing with a question would have.
The last piece of the mechanism is the smallest and does the most work. Reviewers should always feel free to say that something could be better, but when it is not very important, prefix it with something like “Nit:” so the author knows it is a point of polish they may choose to ignore. Without that marker every comment arrives at the same volume, and an author facing eleven notes of unknown weight has to negotiate all eleven. With it, eight are gifts and three are the review.
What is worth blocking on#
The dividing line is not severity, and it is not how strongly you feel. Google’s standard puts it as a claim about the subject matter: aspects of software design are almost never a pure style issue or just a personal preference — they are based on underlying principles and should be weighed on those principles, not simply by personal opinion.
That gives a test you can apply in the moment, before typing. Name the principle out loud. If it comes out as a sentence about what happens to the system — this loses data on a retry, this makes the read path depend on a service that is allowed to be down, this cannot be rolled back — the comment is a blocking one and should say so plainly. If the honest sentence is “I would have written it the other way”, it is a nit, and the review is better for that being admitted in the comment than for it being dressed up as a standard.
One case is worth blocking on that looks like a nit and is not: the change you could not follow, which the author has now explained in a reply. The guidance is to ask for the code to be made clearer rather than to accept the explanation, on the grounds that the comment thread will not be there for the next reader. Resolving that thread on the strength of a reply leaves the confusion in the codebase and moves the record of the answer somewhere nobody will look.
The cost of all this is time, and it is worth stating rather than pretending the good version is also the fast version. A comment carrying its reason takes three times as long to write as a verdict. The compensation is not moral — it is that a review conducted this way tends to end in one round instead of three, and the author usually catches the next instance of the same problem themselves.
IF YOU REMEMBER ONE THING
Before typing a blocking comment, write the principle it rests on in one sentence. If that sentence is about the system, block. If it is about your preference, it is a nit, and saying so costs you nothing.
Where it goes wrong#
The failure mode has a shape and it is recognisable from about the fourth reply.
A reviewer leaves a comment. The author disagrees, briefly. The reviewer restates the point with more detail, because more detail has always worked before. The author restates theirs, now with a benchmark. Somewhere around the sixth exchange the thread stops being about the code: both people are defending a position they have now taken publicly, in writing, in front of the team, and conceding has acquired a cost that has nothing to do with who is right.
What produces this is not temperament. It is that a comment thread has no turn-taking cost and no tone. Each reply is free to write, permanent once written, and read by an audience — three properties that a conversation does not have, and that together make backing down more expensive with every round. Nothing in the thread is capable of ending it, because the only moves available are repeating yourself and giving in.
The reliable exit is to change the medium and then return the result. Two replies is the budget; past that, the exchange goes to a call or a desk, and whatever is decided goes back into the thread as a short summary — including, when it happens, that the reviewer was wrong. That last part is what stops the pattern recurring, because it is the only public evidence the team gets that the argument was ever about the code.
The cousin of this failure runs the other way and is easier to miss: the reviewer who never blocks on anything, waves through the change with a comment about naming, and then owns a share of the outage two weeks later. Approving is a decision with the same weight as refusing, which becomes structurally obvious once part of the reviewing is done by a machine — what a human is still deciding at the merge gate is the same judgement this article is about, with the volume of changes turned up until it can no longer be done by feeling.
The next thing that gets argued about, once code stops being the subject, is nearly always how long something is going to take — and where the error in an estimate actually comes from turns out to be a question about which decisions have been made, not about how carefully anybody guessed.
Questions people also ask
4 QUESTIONSShould I approve a change I would have written differently?
Usually yes. Google's own standard asks reviewers to approve once the change definitely improves the overall code health of the system, even when it is not perfect, on the grounds that there is no perfect code — only better code. Holding a change until it matches the version in your head is a different job from the one review is doing.
How do I say something is wrong without it sounding personal?
Describe the input and the outcome rather than the author or the code's quality. 'This is fragile' is a verdict nobody can act on or check. 'If the retry fires while the first call is still open, this writes the row twice' is a claim that can be tested, and either it is true or you have learned something.
What does prefixing a comment with 'Nit' actually mean?
That it is a point of polish the author may choose to ignore, which is exactly how Google's guidance describes it. The value is not politeness — it is that the author no longer has to guess which comments are conditions of approval and which are asides, and can stop treating every note as a demand.
The author explained it in a reply and it makes sense now. Do I resolve the thread?
Only after the explanation is in the code. Google's guidance is specific here: if you did not understand it, ask for the code to be made clearer rather than accepting the reply, because the next reader will not have the thread. A comment resolved by conversation leaves the confusion in place for everyone who comes later.