🇸🇬 HireDeveloper.sg

Our React Reviews Took 4 Days and Caught Nothing — the 7 Quality Gates That Fixed It in a Month

Developer reviewing a React pull request diff on screen
Panos Petropoulos

Panos Petropoulos

Web Development Expert · 8 September 2026 · 13 min read

TL;DR

  • • If a machine can judge it, no human should comment on it. Formatting, lint, types and bundle size go to CI on day one.
  • • Cap pull requests around 400 changed lines. Above that reviewers skim and approve, and the diff stops being reviewed at all.
  • • A React review answers four questions: where state lives, re-render cost, error and loading states, accessibility of interactive elements.
  • • Set a review latency target in working hours — the timezone gap, not the reviewing, is what turns two days into four.
  • • Type every comment as blocking, suggestion or question. Most review delay is authors guessing which comments stop a merge.
  • • Require evidence, not compiling code. A screenshot, a recording or a test showing the behaviour actually working.
  • • Revisit the gates monthly against real incidents. Change the gates, do not keep adding rules.

The review queue was not the problem. The problem was that four days of review produced eleven comments about naming and zero comments about the re-render that took the search page down the following week.

Here are the seven gates we put in place, in the order we introduced them, and what each one is actually for.

Why review decays on a dedicated team specifically

Two causes compound, and neither is about the people.

Nobody wrote down what a review is for. So each reviewer applies a private standard, and comments drift toward whatever is easiest to see. Naming is easy to see. A subtle state placement bug is not. The review fills with cosmetic feedback and everyone feels productive.

The timezone gap multiplies every round trip. On a co-located team, four rounds of trivial comments cost an afternoon. On a dedicated team split across timezones, four rounds cost most of a week. The cosmetic comments are not just low value — they are expensive.

The fix is not more discipline. It is making the standard explicit and removing every judgement a machine can make from human hands.

TWO GATES, AND NOTHING CROSSES BETWEEN THEMMACHINE GATE — CIFormatting and lint rulesType checkingTest suite and coverage floorBundle size budgetNo human ever comments on these againHUMAN GATE — 4 QUESTIONS1. Where does this state live?2. What re-renders because of this?3. Error and loading states handled?4. Keyboard and focus behaviour?Everything else is optional commentaryThe failure mode this preventsHumans spending four days on what a linter decides in four seconds, while the state bug ships to production.

Step 1 — Separate the machine gate from the human gate

Everything a machine can decide goes into continuous integration: formatting, lint rules, type checking, the test suite, a coverage floor and a bundle size budget. These either pass or block the merge. No human comments on them, ever again.

This is not primarily about speed. It is about removing the interpersonal cost of enforcement. A linter that rejects a formatting choice is a rule. A reviewer who rejects the same choice is a person making a judgement about another person’s work, and on a dedicated team with a client-vendor dynamic underneath it, that gets political fast — usually by everyone quietly agreeing to stop mentioning it.

Step 2 — Cap pull request size and mean it

Set a hard ceiling of roughly 400 changed lines, excluding lockfiles, generated code and snapshots.

Above that threshold, reviewers stop reading and start skimming. They approve because the alternative is two hours they do not have, and the approval is functionally meaningless. A 1,500-line pull request does not receive a stricter review than a 300-line one — it receives a worse one.

The critical part is the response when the cap is breached. An oversized pull request is a planning failure, not a heroic effort. Send it back to be split. On React teams the usual cause is a feature branch that also carried an opportunistic refactor, which is precisely the mixture that makes a diff impossible to reason about.

Building a dedicated React team in Singapore?

We shortlist React engineers who already work this way — small pull requests, evidence attached, opinions about state placement — so you are not retrofitting the process after month three.

Get the shortlist

Step 3 — Write the four questions a React review must answer

Write them down. Put them in the pull request template. These four are mandatory; everything else a reviewer wants to say is optional commentary.

1. Where does this state live, and does it need to live there? Misplaced state is the root cause of most React re-render and synchronisation bugs. State lifted too high re-renders half the tree; state pushed too low gets duplicated and drifts out of sync.

2. What re-renders because of this change? The single most common production React problem we see is a context value or an inline object that silently causes a large subtree to re-render on every keystroke. It never fails in review because review happens on a diff, not on a running application.

3. Are the error and loading states handled? The happy path is always implemented. The failure path almost never is. Ask explicitly what this component shows while data is loading and what it shows when the request fails.

4. Is it reachable and operable by keyboard? Focus handling, keyboard reachability, and whether a div with an onClick is impersonating a button. Cheap to fix in review; expensive and embarrassing to fix after an accessibility audit.

Step 4 — Set a review latency service level

Agree a first-response time expressed in working hours — not calendar days — and measure it.

This matters disproportionately for a dedicated team in Singapore working with stakeholders elsewhere, or a Singapore-based team reviewing work produced overnight. If your reviewer’s working day starts after the author’s ends, every round trip costs twenty-four hours regardless of how fast anyone reads.

Two practical rules make the overlap work. Name a primary and a backup reviewer per area so nothing waits on one person’s calendar. And require that the first response is complete: all comments at once rather than trickled across three visits, because on a timezone gap a trickle turns a one-day review into a four-day one.

WHY THE SAME REVIEW TAKES 4 DAYS OR 1 DAYTRICKLED COMMENTS — 4 DAYSDay 1: two naming comments  →  author fixes, waits overnightDay 2: reviewer notices a test gap  →  author fixes, waits overnightDay 3: a question about state  →  Day 4: approved, re-render bug still presentCOMPLETE FIRST RESPONSE — 1 DAYCI has already settled formatting, types, tests and bundle size before a human looksReviewer answers all four questions in one pass, every comment typed as blocking or notAuthor resolves in one cycle  →  merged, with the state question actually answeredSame reviewer, same author, same code. The difference is process, not effort.

Step 5 — Type every comment as blocking, suggestion or question

Prefix each comment. Three types, nothing more:

  • blocking: this must change before merge.
  • suggestion: consider it, merge either way.
  • question: I want to understand, not to change anything.

This costs one word per comment and removes an enormous amount of friction. A large share of review delay is authors trying to infer which comments actually stop a merge, and defensively addressing all of them — including the musings.

It matters more across a client-vendor relationship than within one team, because a dedicated team will treat every comment from the client as blocking unless told otherwise. That is a rational reading of the power dynamic, and it quietly doubles your cycle time.

Step 6 — Add a production evidence gate

Require the pull request to show that the behaviour works, not merely that the code compiles. A screenshot, a short screen recording, or a test that exercises the actual behaviour.

This is the gate that catches the largest class of React defects, because a diff cannot show you a rendering bug, a broken loading state or a component that works alone and breaks inside its real parent. Reviewing React from the diff alone is reviewing a description of the thing rather than the thing.

Keep the requirement proportionate: a screenshot for a visual change, a recording for an interaction, a test for logic. The point is that somebody ran it.

Step 7 — Review the gates monthly against real incidents

Once a month, list what reached production and caused a problem, then ask a single question of each item: which gate should have caught this, and why did it not?

Sometimes the answer is that no gate covered it, and you add one. More often the answer is that a gate exists but is unenforced, or that the review is drowning in cosmetic comments and the real question got lost. That is a signal to remove rules, not add them.

The failure mode to avoid is a review checklist that only ever grows. A twenty-item checklist is not applied — it is skimmed and signed. Keep the mandatory human list at four questions and let the machine gate absorb everything else.

GateEnforced byWhat it catches
Formatting, lint, typesCIStyle debates, entire classes of trivial defect
Pull request size capCI warning plus policyUnreviewable diffs and hidden refactors
Four React questionsHuman, in templateState placement, re-render cost, failure paths, accessibility
Review latencyMeasured, named reviewersTimezone-driven cycle time inflation
Typed commentsConventionAuthors over-serving non-blocking feedback
Evidence attachedTemplate requirementRendering and interaction bugs invisible in a diff
Monthly gate reviewTech leadChecklist bloat and unenforced rules

What actually changes, and how fast

Expect the machine gate and the size cap to change cycle time within about two weeks — those are mechanical. The four questions take longer to bite, roughly a month, because reviewers need to build the habit of asking about state placement instead of naming.

The honest caveat: none of this compensates for the wrong team. Gates raise the floor and make standards portable when people rotate, which is exactly what a dedicated engagement needs. They do not turn engineers who have never debugged a production re-render into engineers who have. That part is a hiring question — the same one we work through when hiring developers into a growing team, and when structuring a dedicated React team in Singapore from the start.

One regional note: the React talent pool Singapore employers draw on increasingly overlaps with the Gulf, where the same engineers are being recruited for financial and government platform work. We see it in our own pipelines against engineering hiring in Dubai, and it is one reason retention on a well-run dedicated team is worth more than a marginally cheaper rate card.

Frequently asked questions

Why do code reviews on outsourced React teams become slow and low-signal?

Two causes compound. First, nobody ever wrote down what a review is for, so every reviewer applies a private standard, and the comments drift toward whatever is easiest to see: naming, formatting, personal style preferences. Second, on a dedicated or offshore team a timezone gap turns each round trip into a day, so a review with four rounds of cosmetic comments costs most of a week and still misses the defect that reaches production. The fix is not more discipline or more reviewers. It is making the standard explicit and moving everything a machine can judge out of human hands entirely.

What is a reasonable pull request size limit for a React team?

Around 400 changed lines is the practical ceiling, excluding lockfiles, generated code and snapshots. Above that, review quality falls sharply because reviewers begin skimming and approving rather than reading, which is a well-known effect in review research and matches what most teams see in their own defect data. The important part is not the exact number but the response when it is exceeded: an oversized pull request should be treated as a planning failure and split, not waved through with an apology. On dedicated React teams the usual cause is a feature branch that also carried a refactor, which is exactly the combination that makes a diff unreviewable.

What should a React-specific code review actually check?

Four things, and they are worth stating explicitly because they are the ones that reach production when nobody names them. Where state lives and whether it needs to live there, since misplaced state is the root of most React re-render and synchronisation bugs. Re-render cost, meaning whether a change silently causes a large subtree to re-render on every keystroke. Error and loading states, because the happy path is almost always implemented and the failure path almost never is. And accessibility of interactive elements: keyboard reachability, focus handling and whether a div is impersonating a button. Everything else a reviewer might mention is useful but optional.

How do you enforce review standards on a team you do not employ directly?

You automate what you can and contract the rest. Machine-checkable rules belong in continuous integration, where they apply identically to everyone and generate no interpersonal friction. The human standards belong in a short written document referenced in the engagement terms, alongside an agreed review latency and a monthly review of the gates themselves. What does not work is relying on seniority or goodwill, because a dedicated team rotates people and the unwritten standard leaves with whoever knew it. If a rule matters enough to block a merge, it should be either enforced by a machine or written in a document both sides signed.

Ready to build the team these gates are for?

We shortlist dedicated React engineers for Singapore companies and help you set the review process before month one, not after the first incident.

Start your shortlist