Categories
Practices

Code Review Without Friction in a Small Team

On a five-person team, code review can go one of two ways. Either it’s a rubber stamp – “LGTM” thirty seconds after the PR opens – or it turns into a slow-motion argument about tabs versus spaces while the actual feature sits unmerged for three days. I’ve lived through both, and neither is what review is for. The goal is narrow: catch bugs before production, keep the codebase coherent, and spread knowledge of the system across more than one head. Everything else is optional.

Decide what review is actually checking

Before you can fix review friction, agree on what a reviewer is responsible for. In practice that’s usually three things: does this change do what it claims to do, will it break something else that isn’t obvious from the diff, and can the next person who touches this file understand it without asking you. Style, naming preferences, and “I would have done this differently” are not on that list. If your team keeps arguing about formatting, that’s a linter and formatter problem, not a review problem – configure Prettier or Black and stop discussing it in PRs.

Put a number on response time

The single biggest source of review friction on small teams isn’t disagreement, it’s latency. A PR that sits for two days loses context – the author has moved on to something else, and picking it back up costs more than the original review would have. Agree on a norm: reviews get a first pass within a few working hours, not “when I get to it.” Google’s engineering practices guide makes this point directly – a reviewer should respond quickly even if the response is “I don’t have time for a full review today, but here’s a quick pass” (google.github.io/eng-practices – review speed). On a team of five, this is a habit, not a policy document – it just needs one person to model it consistently.

Label feedback by severity

Most review friction comes from ambiguity about whether a comment is a blocker. “Consider renaming this” reads very differently depending on whether the author is expected to act on it before merging. Prefixing comments removes the guesswork:

blocking: this will throw if `user` is null - handle it before merge
nit: could shorten this to a ternary, up to you
question: why do we retry here but not in the sibling function?
praise: nice catch on the race condition in the original PR

This is close to what the Conventional Comments spec formalizes (conventionalcomments.org). You don’t need the full spec – just the habit of marking non-blocking suggestions as non-blocking so the author can merge without a second round-trip.

Keep PRs small on purpose

A 40-line PR gets reviewed in ten minutes. A 900-line PR gets an “LGTM” without being read, because nobody has an uninterrupted hour to actually follow it. If a feature is large, land it in a sequence of small, independently reviewable PRs – behind a feature flag if it isn’t ready to ship. This is more work for the author up front, splitting a change into logical steps, but it’s the single highest-leverage habit for making review fast and actually useful rather than theatrical.

Review your own diff before anyone else does

The fastest review is the one that never needs a second round. Before requesting review, open your own PR as if you were the reviewer – read the diff top to bottom, not your editor’s view of the whole file. This catches the leftover debug print, the unrelated formatting change that snuck in, the TODO you meant to resolve before pushing. On a small team, a self-reviewed PR routinely needs one comment instead of five, which is the difference between a same-day merge and a PR that bounces back and forth for two days.

Assign, don’t broadcast

“PR ready for review” posted to a channel with no assignee diffuses responsibility – everyone assumes someone else will pick it up. On a team of five, just assign a specific reviewer, and rotate who reviews what so knowledge doesn’t pool in one person. If someone owns a part of the codebase, a lightweight CODEOWNERS file will auto-request them without you having to remember.

Know when to skip it

Not everything needs full review. A one-line typo fix, a config value bump, a revert of a change that broke the build – these can go through with a rubber stamp or even bypass review if your team trusts the author and the change is trivially reversible. Reserve careful review for what actually carries risk: anything touching auth, billing logic, data migrations, or public API contracts. Treating every change with the same ceremony is how review turns into overhead instead of a safety net.

None of this requires new tooling or a review policy doc nobody reads. It requires the team agreeing, once, on what review is for and what “blocking” means – and then a couple of people modeling fast, specific, non-personal feedback until it’s just how the team works.