Giving feedback is one of the most high-leverage things a senior engineer does — and one of the most consistently underdeveloped skills in the profession. Most engineers who are technically excellent struggle with feedback because the skills are completely different. Writing good code requires precision and correctness. Giving feedback that changes behavior requires understanding why the behavior exists and what conditions would change it.
This post is about technical feedback specifically: code reviews, design critiques, architecture discussions, and the kind of direct feedback about someone’s technical work that either helps them grow or falls flat.
Why Technical Feedback Usually Fails
Technical feedback fails in two predictable ways.
Too soft to act on. “Nice work overall, but maybe think about the error handling?” leaves the recipient with nothing concrete to do. They don’t know which error cases concern you, whether you’re blocking the PR on this or just noting it, or how much refactoring is appropriate. Nice-work-but feedback creates the feeling of being given feedback without any of the actual substance of it.
Too blunt to receive. “This is wrong” or “you’ve overcomplicated this” is technically correct feedback that gets received as criticism of the person, not the work. The natural defense response shuts down the conversation. The recipient gets defensive, agrees to changes without internalizing them, or disengages from the interaction. None of these outcomes produce genuine improvement.
The failure mode in both cases is the same: the feedback is about the output rather than about the reasoning. Effective technical feedback engages with the reasoning behind the decision — which requires understanding it first.
Understand Before Critiquing
The most important thing you can do before giving technical feedback is establish what the other person was trying to achieve. This sounds obvious, but most code reviews skip it.
Before you say “this is overcomplicated,” ask: what constraints were you working within? What alternatives did you consider? Is there a reason you chose this approach over [simpler alternative]?
This does two things. First, it surfaces information you may not have. The “overcomplicated” solution may be solving a problem you haven’t seen. The design that looks wrong from the outside may be the result of a constraint that isn’t visible in the code. Getting that context prevents you from giving feedback based on an incomplete model.
Second, it shifts the dynamic. Asking before critiquing signals that you’re trying to understand, not to be right. That signal makes the subsequent feedback much easier to receive — because the recipient knows you’ve engaged with their reasoning, not just pattern-matched against a standard.
The Feedback That Drives the Most Change
When the feedback is substantial — not a quick style note but a genuine disagreement about approach — the structure that produces the most change is:
State what you observed, not what you conclude. “The error handling in lines 47–62 returns a generic 500 for three different failure modes” is an observation. “This error handling is wrong” is a conclusion. The observation is easy to engage with — the recipient can verify it, explain why it’s there, or agree to fix it. The conclusion invites defensiveness.
State your concern, not the fix. “When the upstream service times out, the caller gets a 500 with no way to distinguish timeout from a data error. That makes retry logic difficult to implement correctly.” This tells the recipient what problem you’re worried about. It doesn’t prescribe the solution — which means they can apply their knowledge of the codebase to find the best fix, rather than implementing your suggestion regardless of local context.
Make the severity explicit. This might be the most important thing. Is this blocking? Is it a suggestion you’d implement differently but can live with? Is it a question you’re genuinely unsure about? The failure to distinguish “I’d block this PR on this” from “this is something to think about for next time” produces enormous ambiguity that erodes trust over repeated reviews.
Code Review Specifically
Code review is where most engineers give and receive feedback most frequently, and where the skills matter most for the team’s velocity and quality.
A few principles for code reviews that improve rather than frustrate:
Review the small things in the code itself; raise the large things in a conversation. If you have a fundamental disagreement about the architecture of a PR, leaving ten comments about edge cases and then a final comment saying “actually I think we should rethink the whole approach” is the worst possible sequencing. The author fixes all the small things, then gets the big architectural note. Both parties have wasted time.
When the concern is substantial, have the conversation first — in a sync, not as a comment chain. Get alignment on the approach, then review the implementation details.
Be willing to approve things you’d have done differently. Not every code review is a negotiation about the one correct approach. There are often multiple defensible approaches, and blocking a PR because you’d have used a different pattern — when both patterns work — is a tax on velocity with no quality payoff. Reserve blocking reviews for genuine quality problems: correctness issues, security vulnerabilities, performance cliffs, maintainability problems that will compound.
Comment on what you’re uncertain about. “I’m not sure if this handles the case where X — do you know?” is more useful than either assuming it’s correct or asserting it’s wrong. A lot of code review feedback expresses false certainty. The reviewer doesn’t actually know if the approach handles the edge case — they’re guessing. Naming the uncertainty is more honest and often produces more information.
Design and Architecture Feedback
Design feedback is harder than code review because the stakes feel higher (architecture changes are expensive to undo) and the space of alternatives is less bounded.
The most effective design feedback:
Starts with understanding the problem being solved. Before critiquing a design, verify that you agree with the problem definition. A lot of design disagreements are actually disagreements about what problem is being solved. Surfacing that early saves a lot of time.
Engages with trade-offs, not absolute correctness. Most design decisions are trade-offs — latency vs. consistency, development speed vs. operational complexity, flexibility vs. simplicity. Feedback that treats a design as simply right or wrong usually misses this. Feedback that says “this design optimizes for X, but I think we’re underweighting Y because [reason]” is more actionable and harder to dismiss.
Distinguishes what you’d do differently from what you think is wrong. These are different things. “I’d structure this differently” is an invitation to a design discussion. “This is wrong” is a claim that requires evidence. Most design feedback conflates them, which creates confusion about whether the feedback is blocking or advisory.
Feedback on Performance and Growth
The hardest technical feedback is feedback about someone’s overall performance: they’re not growing, they’re operating below their level, they’re blocking their own promotion, or there’s a skill gap that’s becoming a problem.
Two things make this feedback effective:
Specificity over abstraction. “You need to be more strategic” tells someone nothing. “In the last three planning cycles, you’ve proposed implementation approaches before engaging with the problem definition — I’ve seen this pattern in [specific examples]. That’s a significant gap at the senior level, where a lot of the job is shaping what gets built, not just how.” Specific enough to act on.
Agency for the recipient. Feedback that tells someone what’s wrong without a path to address it is demoralizing, not motivating. “I’m worried about your promotion timeline. Here’s specifically what I see as the gap, here’s what operating at the next level would look like, and here’s what I’d suggest doing differently in the next quarter.” The feedback still requires uncomfortable honesty — but it orients toward growth rather than verdict.
The engineers who get the most out of the feedback they give are the ones who follow up. Feedback delivered once and never mentioned again rarely changes behavior. Checking in — “you said last quarter you wanted to work on [thing]; how do you think that’s going?” — is what separates feedback-giving as a practice from feedback-giving as an event.
VividMap helps you track the feedback you give and receive over time — so that skill development investments and their outcomes are visible, not just the moments when something was hard. See how it works.