How I Give Technical Feedback Without Killing Morale
by Eric Hanson, Backend Developer at Clean Systems Consulting
Technical feedback is necessary, occasionally uncomfortable, and often delivered in ways that make people defensive instead of thoughtful. Here's the approach I've landed on after getting it wrong enough times.
The Feedback That Shuts People Down
I've given feedback that landed badly. I thought I was being direct and useful. The person received it as an attack on their competence. They got defensive, or went quiet, or came back with justifications instead of engagement. Nothing improved, and a working relationship got a little worse.
Reflecting on those cases, the pattern was usually the same: I'd treated the feedback as self-evidently correct and framed it as a correction rather than a conversation. I was right about the technical issue. I was wrong about how I handled the human in front of me.
Good feedback requires getting both right.
Separate the Code From the Person
The most reliable principle I've found: comment on the code, not the developer. "This function is hard to follow" instead of "you wrote this in a confusing way." "This approach has a performance problem" instead of "this is slow because you didn't think about indexing."
The distinction seems small. The psychological effect is significant. When you attach the problem to the person, they have to defend themselves. When you attach the problem to the artifact, they can engage with it more objectively — as a thing they created, not a reflection of who they are.
This becomes especially important with junior developers, who often haven't yet separated their identity from their code. For someone early in their career, "your code is bad" and "you are bad at your job" can feel like the same sentence. They aren't, but the feedback has to work in the real world, not the ideal one.
Be Specific About the Problem and Honest About the Stakes
Vague feedback is useless at best and demoralizing at worst. "This doesn't feel right" gives the recipient nothing to work with and implies something is wrong without explaining what. They either guess and implement the wrong change, or they come back asking what you meant, which adds friction for everyone.
Specific feedback requires you to do the work of actually understanding why something is a problem:
- What's the concrete failure mode?
- Under what conditions does it manifest?
- How significant is it — a correctness issue, a performance concern, a style preference?
Knowing the stakes matters. If something is a genuine correctness problem, say so plainly. If it's a preference, say that too. People receive "I'd consider renaming this" very differently from "this will cause incorrect behavior when the input is empty." Both are valid feedback. They need to be distinguished.
Questions Before Conclusions
When I'm looking at code that seems wrong or suboptimal, my first instinct now is to ask rather than assert. "What happens when the user sends a null value here?" rather than "you haven't handled nulls."
This isn't passive-aggressive — I'm not using questions to disguise an accusation. I'm genuinely trying to understand whether the author thought about this case. Sometimes they did and the handling is elsewhere. Sometimes the question itself surfaces the issue for them before I have to spell it out.
When people reach the conclusion themselves, even prompted by a question, they own it differently than when it's handed to them. The insight sticks.
Timing and Channel
A lot of feedback goes badly not because of content but because of context. Public feedback in front of peers is more threatening than private feedback, even if the words are identical. Feedback delivered when someone is stressed or time-pressured lands differently than the same feedback in a calmer moment.
I now think about this explicitly. If the feedback is significant — something that touches on someone's core work or involves a pattern I've been seeing repeatedly — I'll have it in a private conversation, not a PR comment. PR comments are fine for specific code-level things. Patterns in someone's work, larger concerns about approach, anything that might feel personal — those deserve a real conversation.
Async written feedback lacks tone, context, and the ability to course-correct in real time. For anything beyond routine code comments, a conversation is almost always better.
What to Do When Feedback Isn't Received Well
Occasionally you give feedback carefully and it still lands badly. The person gets defensive or dismissive. In that moment, the instinct is to either back off entirely or double down. Neither is usually right.
I try to understand what they're defending. Sometimes it's the decision itself — they genuinely believe their approach is correct. Sometimes it's their identity — they feel criticized as a developer, not just for this specific choice. The conversation you need to have is different in each case.
If it's about the decision, stay in the technical domain. Ask what would change their mind. Offer to find concrete evidence — a benchmark, a test case, an example from the codebase. Keep it specific and keep the relationship intact.
If it's about identity, the technical issue can wait. The more important thing is re-establishing that the feedback is about the work, not a judgment of the person. That sometimes requires explicitly saying so.
The goal of feedback isn't to be right — it's to leave the code better and the person more capable of improving it themselves next time.