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.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

How to Build a Network Without Feeling Fake

Networking often feels like acting—smiling, small talk, pretending to care. But real connections don’t come from performance; they come from being human.

Read more

How Legacy Systems Trap Engineering Teams

Legacy systems can feel like a trap—working, but only barely, and often at the cost of the team trying to maintain them.

Read more

Google and Microsoft Opened R&D Centers in Warsaw — and Took the Best Backend Developers With Them

Warsaw's engineering talent is world-class. Google and Microsoft figured that out before most startups in the city had a chance to compete for it.

Read more

Why Berlin Scaleups Use Remote Backend Contractors to Ship Faster Without Headcount

You've got funding, a roadmap, and three backend tickets that have been sitting untouched for six weeks. In Berlin's hiring market, that gap between what you need built and who's available to build it is expensive.

Read more