The first time I watched a senior engineer tear apart a junior’s pull request, I didn’t say anything. The feedback was technically correct. Every comment pointed to a real issue, a naming convention, an edge case, a slightly inefficient pattern. Nothing was wrong with the review itself.
Everything was wrong with how it landed.
The junior didn’t submit another PR for three days. When they did, it was half the size it should have been, over-engineered in the places where the senior had left comments and under-thought everywhere else. They’d learned a lesson, but not the one we wanted them to learn. They’d learned that code review was a test you could fail.
Code review should make everyone smarter. If it’s only making people careful, you’re doing it wrong.
The gatekeeping instinct
I understand where it comes from. When you’re a senior engineer and you’ve been responsible for a codebase for years, reviewing someone else’s code feels like defending your territory. You know where the landmines are. You know which shortcuts will cause pain in six months. You have strong opinions about how things should be structured, and you’ve earned those opinions through experience.
The problem is that “earned through experience” can easily become “enforced through authority.” And when a senior engineer starts treating code review as quality control rather than collaboration, the dynamic shifts from “let me help you make this better” to “let me tell you why this isn’t good enough.”
The difference between those two things is subtle in text. It’s in the tone of a comment, the ratio of questions to demands, whether the feedback is “consider doing X because Y” or just “change this.” In an office, you can soften a tough review with body language, a smile, a follow-up conversation at the coffee machine. In a remote team, the review IS the communication. There’s nothing else to cushion it.
The senior who feels threatened
Here’s something I’ve seen multiple times that nobody talks about openly: the senior engineer who starts to feel threatened by the junior.
It happens like this. You hire a junior who’s fresh, enthusiastic, and fast. They reach for tools the senior has never used. They write code in patterns the senior isn’t familiar with. They move quickly because they don’t yet know all the reasons to be cautious.
The senior, who has been the technical authority on the team, starts to feel something uncomfortable. Not anger exactly, more like uncertainty. “Am I still the best engineer here? Do I still know enough? Is this person going to make me look slow?”
That feeling, if it goes unaddressed, poisons code reviews. The senior starts nitpicking things that don’t matter. They block PRs on style preferences rather than substance. They leave comments that are technically accurate but emotionally loaded. And the junior, who has no idea what’s going on beneath the surface, interprets it as “my code isn’t good enough” and starts shrinking.
I’ve learned to recognise this dynamic, partly because I’ve had to get past it myself. When someone younger and faster comes in with a technique I’ve never seen, my first instinct used to be scepticism. “That’s not how we do it.” “That won’t scale.” “Have you considered…” followed by a concern that was really just discomfort dressed up as diligence.
Getting past that was one of the most important things I’ve done as a leader. The juniors aren’t a threat. They’re an update. They’re bringing techniques from the world that exists now, not the world that existed when I learned. And if I can’t learn from them while also sharing what I know, I’ve stopped being a good engineer.
How we actually do it
At SafeNav, code review is async. Someone opens a PR, reviewers comment when they get to it, and the author responds. It’s not complicated.
What makes it work isn’t the process, it’s the culture around the process. Here’s what I’ve tried to establish:
The senior engineers review and approve. I mainly listen. If something doesn’t make sense to me, I’ll ask a question, but I try not to override or direct. The seniors own the technical quality of the codebase, and if I’m constantly swooping in with opinions, I’m undermining their authority and making myself a bottleneck.
Questions over statements. “Why did you choose this approach?” is a better review comment than “this should be done differently.” The question invites explanation, which might reveal that the author had a good reason you didn’t consider. The statement just creates compliance.
Approve with comments. If a PR is fundamentally sound but has minor issues, approve it and leave the comments as suggestions. Don’t block a merge on a variable name. The junior who sees “approved” alongside constructive feedback learns that their work is valued AND that there’s room to improve. The junior who sees “changes requested” because of a variable name learns that nothing they submit is ever good enough.
Review the thinking, not just the code. The most useful code review comment I’ve ever received was “this works, but walk me through why you structured it this way.” It wasn’t criticism. It was an invitation to explain my reasoning, and in explaining it, I realised I’d made an assumption I couldn’t justify. That’s what good review does, it surfaces the thinking behind the code.
The timezone question
I try to keep most of the team in overlapping timezones, which makes async review workable. When there’s a gap, I find the core hours where everyone is awake and that’s when reviews happen.
The worst thing you can do is leave a PR sitting for 24 hours because the only reviewer is asleep. That’s a day of blocked progress, and it teaches people to submit smaller, less ambitious PRs to reduce the risk of a long wait. Which means you get more PRs, each with less context, and the overall review burden goes up.
If you’ve got a team split across timezones, you need more than one person capable of reviewing any given area of the codebase. That’s not just a review concern, it’s a resilience concern. And it’s another argument for group review, because it spreads the knowledge around.
The Friday review session (an idea I’m exploring)
I’ve been thinking about adding a synchronous group review session, maybe on Friday afternoons. Not to replace async review, but to supplement it. Pick one or two interesting PRs from the week and walk through them together as a team.
The value wouldn’t be in catching bugs, the async process should handle that. The value would be in shared learning. When the whole team sees how someone approached a problem, everyone’s mental model of the codebase expands. The junior sees how the senior thinks about architecture. The senior sees the new tools the junior is bringing in. And everyone gets context that they’d miss if they only ever reviewed their own assigned PRs.
I haven’t implemented this yet, so I can’t tell you it works. But the idea is grounded in something I believe strongly: the more everyone on the team understands the whole codebase, the better the team gets. Code review is the cheapest way to spread that understanding, and a group session would accelerate it.
The teaching mindset
The fundamental shift I want to advocate for is this: code review is teaching, not testing.
When you review someone’s code with a teaching mindset, your comments look different. Instead of “this is wrong,” you write “here’s what I’d consider and why.” Instead of blocking on style, you approve and share a resource. Instead of rewriting their code in the review comments, you ask them to reconsider a specific decision and trust them to find a better solution.
The gatekeeping mindset says “my job is to prevent bad code from being merged.” The teaching mindset says “my job is to help this engineer write better code next time.” The first one maintains quality. The second one improves it.
And here’s the thing about the senior who feels threatened by the junior: the teaching mindset is also the cure. When you frame review as mutual learning, the senior isn’t losing status by acknowledging the junior’s new tools, they’re gaining knowledge. And the junior isn’t being tested, they’re being mentored. Both people walk away better than they started.
That’s what team sport means. Not that everyone plays the same position, but that everyone gets better because they’re playing together.