A founder I respect told me last month that Autter sounded "too aggressive." He was using a review tool that posted comments on his PRs, and his team had quietly stopped reading them. He was thinking of switching. He wanted to know if we could just leave a comment instead of blocking the merge.
I asked him how many bugs his current tool had caught in the last month.
He couldn't tell me.
That conversation is the entire blog post in three lines, but I'm going to write the rest anyway because the question keeps coming up and the answer matters more than people think.
Every code review tool in the market posts comments. We block the merge. That one design decision changed how the entire product got built, what we sell, who we sell it to, and what the moat looks like.
Comments are advice. Blocks are infrastructure.
This is not a stylistic difference. It is a category difference.
Comments Are Where Good Intentions Go to Die

There's a category of software that I have started calling "well-intentioned advisory." Static analyzers that file warnings nobody triages. Linters that became opt-in. Security scanners that stopped failing builds and started filing tickets nobody reads. Code review bots that post forty inline comments on a 200-line diff and get muted in Slack within a week.
All of these tools were built by people who cared. None of them are doing the job they were built to do.
The pattern is always the same. Tool ships. Tool is strict by default. Developers complain. Tool is loosened. Loosened tool catches less. Catches less means fewer flagged issues. Fewer flagged issues means it stops feeling annoying. Stops feeling annoying means nobody complains. Nobody complains means nobody renews, because the tool has gradually optimized itself into the background.
“A tool that nobody complains about is usually a tool that has stopped doing anything.”
Comments occupy this exact space. The default failure mode of a comment is to be scrolled past at 4:47pm on a Friday by an engineer who just wants to merge their PR before the weekend. The default failure mode of a block is that someone has to deal with it.
These are not the same product. They look like the same product on a marketing page. They are not.
The Quiet Math of Comment Fatigue

Pull up any large repo and look at PRs from the last 30 days. Count the inline comments left by automated tools. Now count how many of those comments resulted in a code change before merge.
The ratio is brutal. We have done this exercise with several teams as part of pilot conversations. The action rate on automated PR comments, in the codebases we have looked at, sits somewhere between 6 and 15 percent. The rest of the comments get marked resolved without a corresponding diff, get ignored entirely, or get a thumbs-up reaction and then nothing.
This is not a developer problem. This is a UX problem. When you put a comment in a PR thread, you are competing for attention with the actual review, with team chat, with whatever the developer was building before they opened the PR, and with the merge button two scrolls down. Comments lose that fight by default.
“The action rate on automated PR comments sits between 6 and 15 percent. The rest is theatre.”
The tools know this. The tools have known this for years. The reason they keep posting comments instead of blocking is not because comments work better. It is because comments are a safer product decision. A comment cannot make anyone angry enough to churn. A block can. And so the entire category has converged on a UX pattern that protects the vendor's renewal rate at the expense of the customer's actual security posture.
This is the part nobody wants to say out loud. Advisory tools are designed to be ignorable. That is a feature for the vendor. It is a bug for the user.
Lesson
The default state of a comment is "ignored." The default state of a block is "addressed." Pick the default that matches the job you actually want done.
What Blocking Actually Does

Blocking does three things that commenting cannot do, and these three things are why we built the entire product around it.
It forces the conversation to happen now, when the context is still loaded. The window where a developer can quickly understand what their own code does is short. It closes the moment they tab over to something else. A comment that gets read three days later is a comment that gets read by someone who has to re-page in the entire change to make sense of it. A block that fires the second the PR is opened is read while the diff is still warm. The fix takes two minutes. The same fix three days later takes thirty.
It creates an actual decision moment. When you block a merge, somebody has to make a call. Either fix the issue or override the gate. Both of those actions are logged. Both leave a trail. The override path is intentional, traceable, and reviewable. The "I read the comment and decided to merge anyway" path looks identical in the git history to "I never read the comment in the first place." Blocking gives you accountability that commenting cannot, because there is no comparable mechanic to "ignored a comment."
It moves the pain to the right place. Catching a bad change at the merge button costs two minutes. Catching it in production three weeks later, after four other PRs have stacked on top of the bad one, costs a week. Every system has some drag in it somewhere. The question is where you decide to put it. Most teams put it at the worst possible spot, which is wherever the developer no longer remembers what they wrote.
“The merge button is the cheapest place in the entire pipeline to push back.”
Blocking is the only one of these that meaningfully shifts behavior. The other two follow from it. Without the block, the conversation does not happen at the right time, and the decision does not leave a trail. With the block, both come for free.
The Objection We Get the Most
The most reasonable pushback against blocking goes like this: "False positives are going to ruin our developer experience. One bad block and the whole team will hate the tool."
This is correct, and it is the entire reason we have spent disproportionate engineering time on suppression. False positive rate is not a metric we manage in a quarterly review. It is the only metric that matters. If a merge gate has a high false positive rate, it is worse than no merge gate at all, because it teaches the team to override blocks reflexively, and once that habit forms, the gate is functionally turned off.
This is also the answer to why a lot of incumbent tools chose comments over blocks in the first place. Comments are the safer product decision precisely because false positives in a comment are forgivable. False positives in a block are not. The bar to ship a blocking tool is significantly higher than the bar to ship a commenting tool, and most of the market quietly took the easier path.
We took the harder path because the easier path is a category that does not work.
False positive suppression in Autter is contributor-aware, repository-aware, and learns from override patterns. If your team has consistently overridden a particular class of finding because it is wrong in your context, that finding gets suppressed for that codebase. Not globally. For you. The tool gets quieter as it gets to know your team, not louder. This is the only way blocking can work as a long-term default.
Lesson
If you are going to block, you have to earn the right to block. False positive suppression is not a feature. It is the foundation under everything else.
This Is Infrastructure, Not a Feature

The deeper reason we block instead of comment is that blocking is the only mode that integrates with the existing governance layer of GitHub. Branch protection rules are blocking infrastructure. Required status checks are blocking infrastructure. CODEOWNERS is blocking infrastructure. The entire native vocabulary of "this code cannot ship until X" is built around enforcement, not advice.
A tool that lives in this layer compounds. Contributor patterns get learned. Repository-specific suppression lists grow. Migration risk profiles develop. The longer the tool runs, the better its judgment gets, because every override and every approved block becomes training signal for the next decision. This is the same reason GitHub itself becomes harder to leave the longer you use it. Your governance is captured in the platform, and the platform gets smarter about your team over time.
A tool that lives in the comment layer does not compound. Comments are stateless. The tool posts the same comments next month that it posted last month, because there is nowhere for the learning to live. Every PR is day one again.
“Comments are stateless. Blocks compound.”
This is also why the merge gate is the right surface area for the next decade of code review, not the comment thread. The comment thread is a feed. Feeds do not have memory. The merge gate is a checkpoint. Checkpoints do.
The companies still shipping comment-based review tools are betting that the AI generation wave will be advisory. They are going to lose that bet. The volume of code generated by AI is going to keep climbing, the average reviewer is going to have less context per PR, and the only way to keep up is to move enforcement to the place where the decision is structurally captured. That place is the merge button.
The Real Lesson
If you are evaluating code review tools right now, ask one question.
What does the tool actually do when it finds something wrong?
If the answer is "it tells you," that is an advisory tool. It will not change your team's behavior. It will not catch the bug that ships on a Friday afternoon. It will not survive the third quarterly cycle of "we are not seeing enough value."
If the answer is "it stops the merge," that is enforcement. That is infrastructure. That is the thing you actually wanted when you started looking for a code review tool in the first place.
We block the merge button because the merge button is the last point in the pipeline where the cost of being wrong is small. Every other intervention happens too late. Every advisory layer pretends to be that intervention without actually being it.
There is no version of code review that works without somebody, at some point, having the authority to say no. We built that somebody. It happens to be an otter.
Building Autter in public. We're a merge gate that does not post a comment, does not file a ticket, and does not gently suggest you look at line 247. We block. If that sounds like the kind of layer your team has been quietly missing, drop us a line at hi@autter.dev or book 30 minutes.
P.S. Tanvi read this draft and pointed out that I used the word "friction" seven times in one section. I argued that friction is the right word and there is no good synonym. She said drag, pain, resistance, and cost all work and that I was being lazy. I rewrote the section. The version you just read has fewer frictions in it. She is usually right about these things :/
