The PR has 47 comments. Variable names, missing error checks, a test that asserts the mock instead of the contract. The comments are real and they are useful. None of them are about the approach.
The approach was the part that determined which files got created, which abstractions were introduced, which constraints got encoded. By the time the PR opened, the author had been living in the implementation for two days, made dozens of small decisions, and developed conviction about the direction. The reviewer opened the PR when they had bandwidth, which was later still. A comment that says “did you consider doing this differently” costs the reviewer one line to write and costs the author a rework they may not have the week left to do.
So the reviewer doesn’t write it. They write about the implementation, not the architecture. They catch the variable name. The architecture got through because feedback on it arrived too late to be useful and too expensive to act on.
The cost is never visible in any single PR. Every reviewed PR looks fine – comments were addressed, suggestions applied, approval given. The system accumulates approach debt that doesn’t show up in any diff. The wrong abstraction survives because nobody said anything when the first draft was designed, and by the time the tenth caller has inherited it, changing it is too expensive to justify. The failure is invisible because it’s distributed across time, not located in code.
The fix isn’t “review earlier.” The fix requires understanding why PR review colonizes the whole process.
PR review has a button. It has timestamps, audit trails, tooling that tells you which comments are resolved and which are open. It has accountability – the approval is recorded, the merge is logged, the history attributes every line to its author and its reviewer. The earlier feedback loop has none of this. The design conversation lives in a Slack thread that scrolls offscreen, or a quick sketch in a Confluence page nobody revisits, or a conversation beside a whiteboard that was erased the next morning. No button. No audit trail. No field in any schema that says “this approach was reviewed.”
The protocol doesn’t have the fields. The join between “what we agreed to build” and “what got built” fails because the shared schema for design review doesn’t exist. Every team I’ve been on that has this problem has the same root: the early feedback loop is informal and the late one is formalized. The formality gap is the architecture’s exposure.
When the early loop works, it’s because someone enforced a shape. A design doc that must circulate before code gets written. An RFC template that asks the same questions every time. A thirty-minute whiteboard session where the relevant people are in the room and the output is photographed and linked from the ticket. The shape doesn’t have to be heavy. It has to exist.
The shape most teams land on is “the senior person approves things before they’re built.” That works until the senior person burns out, or the team grows past their bandwidth, or the decision that needed scrutiny looked small enough to skip. The shape that scales is one that doesn’t depend on a particular person remembering to enforce it.
What it feels like to give late feedback: you open the PR on Friday. The author shipped it Wednesday. You see that the approach assumes a constraint that isn’t required, and the simpler version would be a third of the code. You type the comment, delete it, type it again. You know the author has already moved on mentally. The next ticket is in progress. The context has been swapped out. Your feedback, if they act on it, costs them a day of rework and a week of accumulated frustration that the work they already did is being undone. If they don’t act on it, the system absorbs the cost silently. Either way, the outcome was determined by the timing, not the content of the feedback.
What it feels like to receive late feedback: you pushed the PR Wednesday afternoon. Friday morning a comment arrives that questions whether the whole approach was necessary. You read it. They’re right. You now have to choose between rebuilding two days of work or shipping something you know has a better shape. The third option – the one you didn’t articulate but acted on the last three times this happened – is to defend the approach, address the surface comments, and merge. The review record is clean. The better shape never existed.
The same team that considers itself review-rigorous can accumulate a year of approach debt this way. The PRs look reviewed because they were. The approach was never in the PR to be reviewed. It was in the author’s head two days before the PR opened, and by the time anyone else saw it, the window for structural feedback had already closed.
The teams that avoid this aren’t distinguished by reviewer diligence. What distinguishes them is whether the window exists as a named part of the process. The teams I’ve watched avoid this all have a point in the workflow where the approach is the artifact under review, and that point comes before implementation, and it has its own tooling: a template, a meeting, a document convention. The artifact is lighter than a full spec and heavier than nothing. It says: here’s what I’m going to do, here’s why, here’s where it touches existing things, here’s the part I’m least sure about. The review on that artifact is the real architecture review. The PR review that follows is verification that the implementation matched the agreed approach.
The artifact doesn’t need to be ceremonial. The best version I’ve seen was a paragraph in the ticket description, written before any code, with a checkbox that said “approach reviewed.” The checkbox mattered more than the paragraph. It created a moment that had to be acknowledged before anyone spent two days in an editor.
Review isn’t a quality gate. It’s a communication protocol with a temporal structure. The structure most teams have formalized is the late message – the one that arrives after the work is done, when the cost of change is highest and the signal it carries is most likely to be discarded. The early message – the one that shapes the work before it starts – is left informal, ad-hoc, dependent on the right people being in the right thread at the right time.
The protocol doesn’t have the fields for the early message. Teams that fix this don’t try to make the late message earlier. They make the early message formal. Same rigor, sooner. The checkbox that says “approach reviewed” costs less than the rework that happens when nobody checked.
