Jump to content

7 Code Review Behaviors That Quietly Destroy Team Morale

Engineering Culture Garrett Marlowe

The Fastest Teams Make Code Review Boring

Healthy code review feels procedural and uneventful. The reviewer checks known risks, leaves comments the author can act on, and makes the approval path obvious. Nobody needs to win an argument.

Seven Repairs

  • Personal preference: Label optional taste and automate documented style rules.
  • Drive-by approval: Match review depth to scope, reversibility, and operational risk.
  • Scope ambush: Keep adjacent redesign work outside an agreed change unless safety or correctness demands it.
  • Expertise tests: State the observed condition, likely impact, and possible alternative.
  • Vague vetoes: Give every blocker a location, consequence, and required outcome.
  • Queue silence: Assign an accountable reviewer and publish availability.
  • Reviewer pile-on: Give one person responsibility for consolidating feedback and making the final call.

Review cycles stretching beyond approximately 36 to 48 hours usually point to process friction rather than unusually deep technical scrutiny. Long threads may look rigorous from a distance. Up close, they often contain unclear ownership, indirect language, and architecture decisions that arrived several weeks too late.

I use three practical tests for review behavior. Does it improve risk detection? Does it give the author an actionable next step? Does it keep ownership of the decision clear? A habit that fails those tests is ceremony, regardless of how sophisticated the comment sounds.

Common Failure Modes

  1. Treating personal preference as a defect
  2. Approving without actually reviewing
  3. Redesigning the system after the code is written
  4. Turning questions into expertise tests
  5. Blocking with vague verdicts
  6. Staying silent until the change becomes urgent
  7. Letting every reviewer pile onto the same thread
  8. Writing a review contract
Image showing review_criteria

1. Treating Personal Preference as a Defect

“Why would we name it this way?” looks like a question. In practice, the author must decode whether it means “rename this before merge,” “our convention says otherwise,” or “I would have chosen another name.” That decoding work adds no value to the software architecture.

Useful reviews separate four categories:

  • Correctness defects produce wrong behavior or violate an explicit requirement.
  • Maintainability concerns make future changes materially harder or riskier.
  • Documented conventions apply a rule the team has already accepted.
  • Optional preferences describe an alternative with no required action.

The comment should name its category. “Optional: I find accountById easier to scan” costs almost nothing to interpret. “This name is confusing” starts a negotiation over taste.

Linters and formatters can remove entire categories of style disputes, cutting hundreds of lines of manual comments from a repository each month. Automate the rule if the team genuinely cares about it. Repeatedly blocking on undocumented taste makes approval depend on who opened the review that morning, which is a miserable substitute for engineering standards.

2. Approving Without Actually Reviewing

A drive-by approval creates the appearance of scrutiny while handing the risk straight back to the author. The green check mark becomes decorative compliance.

The signs are familiar: a near-instant approval, silence on a risky migration, or approval based entirely on trust in the author. A pull request in the range of 500 lines approved in under three minutes has not received a thorough reading. For diffs exceeding nearly 400 lines, even a three-to-five-minute approval cannot plausibly account for every changed line, much less the behavior around it.

Small, reversible changes deserve a lighter pass. A copy correction and a cross-service API modification should never consume the same review effort. Set depth according to scope, reversibility, and operational risk. That keeps the process lean without pretending every green check carries equal evidence.

Approval should mean, “I applied an appropriate level of scrutiny and accept the remaining risk.” Anything weaker should use a comment instead.

3. Redesigning the System After the Code Is Written

The pull request implements an agreed API change. Tests pass. The diff stays inside the expected boundary. Then a reviewer blocks it until the author replaces an unrelated abstraction in an adjacent legacy module.

This is the scope ambush: architecture discussion postponed until implementation, then presented as a merge condition. A bug fix blocked by a demand to rewrite an adjacent legacy module can expand the modified file count by a factor of approximately three or more. The targeted repair has now become a high-risk deployment with a larger rollback surface.

Late review can still uncover a genuine correctness or safety problem. That discovery belongs in the current change because shipping known harm would be absurd. Opportunistic redesign requests belong in a separate proposal with their own owner, rationale, and acceptance criteria.

A clean response is direct: “The current implementation satisfies the agreed API behavior. Please identify the correctness or safety issue that requires the abstraction rewrite; otherwise, we will track that redesign separately.” This protects scope without treating architecture concerns as irrelevant.

4. Turning Questions into Expertise Tests

“Have you considered what happens under load?” conceals both the observed problem and the reviewer’s expected answer. The author now has to prove competence through a defensive essay.

Indirect round-trip questions can delay thread resolution by just about 12 to 24 hours at a time. The technical issue may be simple; the latency comes from making another person guess what the reviewer already believes.

Image showing review_conversation

A status-testing question sounds like this: “Are you sure this cache is safe?” A useful comment names the evidence: “This cache has no eviction path, so keys can accumulate for the life of the process. Please add a bound or explain where cleanup occurs. An LRU policy is one possible implementation.”

That structure preserves room for the author to supply missing context. It also moves the discussion back to code behavior, where it belongs.

5. Blocking with Vague Verdicts

“This feels wrong.” “Needs cleanup.” “Not production ready.” Each phrase can carry blocking force while supplying no testable objection.

The author must guess at two things: the alleged defect and the conditions for approval. Predictably, the thread expands. Once a discussion exceeds approximately 15 replies on a single line, the team is usually missing an architectural decision rather than debating a localized defect.

Blocker Anatomy

  1. Location or behavior: Identify the code path or runtime condition.
  2. Concrete consequence: Explain the failure, risk, or maintenance cost.
  3. Required outcome: State what must be true before approval.
  4. Implementation status: Clarify whether the proposed fix is required or merely a suggestion.

For example: “Blocking: retries in sendInvoice can submit the same payment twice after a timeout. Approval requires an idempotency guard. The suggested request-key approach is optional.” The author can now fix the defect, offer an equivalent safeguard, or challenge the premise with evidence.

6. Staying Silent Until the Change Becomes Urgent

An unclaimed pull request sits untouched. A release approaches, another branch needs the code, and extensive feedback suddenly appears. Every comment may be valid, yet the timing converts routine work into an emergency.

Reviewers often carry overloaded queues. Authors also contribute to the problem when they omit context, fail to identify the risky areas, or assign nobody accountable for the first pass. Silence thrives when ownership stays implicit.

One engineering team imposed a strict four-hour review target backed by automated chat pings. After three weeks, the team dropped it because unread “LGTM” approvals spiked. The metric rewarded response speed while degrading review quality. That failure pattern deserves to happen once, then become institutional memory.

Pull requests left untouched for approximately four to five days frequently need rebasing, introducing secondary regression risk before review even begins. Teams should publish reviewer availability, assign an owner, and define their own response expectation. A response can mean claiming the review and stating when it will happen; it need not mean instant approval.

7. Letting Every Reviewer Pile onto the Same Thread

Adding a fourth or fifth reviewer to a standard feature branch rarely uncovers a fresh defect. It does reliably add another 24 to 48 hours to the merge timeline.

The morale damage comes from coordination failure. One reviewer requests a helper method. Another insists the logic remain inline. A late arrival reopens a settled naming debate. The author ends up answering several incompatible versions of the same review while nobody owns the final decision.

Specialist input still matters for core security modules, database schema migrations, and cross-service API contracts. Those high-blast-radius changes require multidisciplinary sign-off. That is the specific exception; routine feature work gains little from collecting spectators.

Assign a primary reviewer to consolidate duplicate objections, resolve conflicting prescriptions, and state when approval conditions have been met. Other reviewers can contribute expertise without creating parallel chains of command.

Write a Review Contract

Teams usually ask how to improve review tone. Tone helps, but a written operating agreement carries more weight because it defines what comments mean.

Start with explicit labels such as blocking, question, suggestion, and follow-up. Teams that adopt explicit comment labels often see review turnaround stabilize within approximately two to three sprint cycles. The labels remove guesswork without requiring elaborate developer tooling.

The contract should also name the primary reviewer, identify changes that require specialist sign-off, define how authors escalate conflicting feedback, and set a response expectation based on the team’s actual availability. Keep it short enough to read before opening a pull request.

Boring by Design

Require every blocking comment to state the affected behavior, concrete consequence, and approval condition. Label everything else as optional or investigative.

Make that blocker format the team’s default review contract and enforce it consistently. Code review should detect risk and move work forward; status games can find somewhere else to live.

Never Miss an Update

Fresh insights every week.

No spam. Unsubscribe anytime.

Your Thoughts

Share your thoughts.

Join the Discussion

Customise cookies