Why this matters
Most teams I have seen do not fail because of technical debt or poor architecture. They fail because feedback stops flowing. Someone stops saying the hard thing. Someone else stops hearing it. The gap between what people think and what they say grows wide enough to swallow the work.
I have been on both sides of this. I have given feedback that landed badly, not because it was wrong but because I delivered it in a way that made the person feel attacked rather than helped. I have received feedback that I initially dismissed, only to realise six months later that the person was right and I had wasted half a year defending a position I should have let go of sooner.
Both are skills. Neither comes naturally. Both can be learned.
Giving feedback
The first thing to understand about giving feedback is that your job is not to be right. Your job is to be useful. These are related, but they are not the same thing.
Being right means the thing you said was accurate. Being useful means the person you said it to was able to do something with it. You can be right and useless at the same time. Engineers do this constantly. "This code is a mess" is right. It is also useless. The person already knows it is a mess. What they need is a path forward, not a verdict.
Before you give any piece of feedback, ask yourself two questions: what specifically is the problem, and what would a better version look like? If you cannot answer both, you are not ready to give the feedback yet. Think longer.
Be specific. Vague feedback — "this could be cleaner", "I am not sure about this approach" — is worse than no feedback at all. It creates anxiety without direction. The person does not know what to fix, so they either fix everything or fix nothing, and either way the relationship between you has slightly degraded.
Feedback is a gift. Like all gifts, it says as much about the giver as it does about the recipient. Give the kind you would want to receive.
Choose the right moment. Feedback delivered in public, in front of peers, is a very different act than feedback delivered in a 1:1. The first can be necessary — when a pattern affects the whole team, naming it in the team context is sometimes right. But individual performance feedback, feedback about behaviour, feedback that touches on someone's judgment or professional competence — that belongs in private, always.
Separate the observation from the interpretation. "This query will cause a full table scan on a 50 million row table in production" is an observation. "You clearly didn't think about performance" is an interpretation. The first opens a conversation. The second closes it.
The line you cannot cross
There is a line between feedback about work and feedback about character. Cross it and you have not given feedback, you have made an accusation.
"This implementation doesn't handle the edge case where the user has no payment method" is about the work. "You always miss the edge cases" is about the person. The first is useful and true and actionable. The second may also be true, but it does not help and it damages trust in a way that is very slow to repair.
A useful heuristic: if the feedback would still be true if a completely different engineer had written the code, it is about the work. If it is only true because of who wrote it, you have drifted into character territory. Stay on the work side of that line.
Watch your tone. In written feedback especially, what sounds clinical in your head can land as contemptuous. Read it back before you send it. Ask: if someone sent this to me about my code, how would I feel? Not so that you soften every edge, but so that you are intentional about which edges are necessary.
⚠ Gotcha
Patterns are not the same as instances.
One bad PR is a bad PR. Seventeen bad PRs with the same issue is a conversation you need to have in person, not in seventeen separate PR comments.
In code review specifically
Code review is the most common feedback context in engineering and also the most commonly done badly. A few things I have found useful.
Distinguish between blocking issues and preferences. If something will break in production, say so clearly and explain why. If something is a style preference or an approach you would have chosen differently, mark it as such. "Nit:", "Optional:", or "My preference, but yours works too:" are useful prefixes. They tell the author what is load-bearing and what is not.
Ask questions instead of making declarations. "Why did you choose this over X?" is different from "You should have used X." The first respects that the author may have had a reason you are not aware of. You might learn something. At minimum you understand the decision better before you challenge it.
Approve what is good enough. Perfect is not the goal. Shipped and correct is the goal. If a PR is safe, does what it says, and does not introduce debt you cannot live with, approve it. Save your thoroughness for the things that genuinely need it.
✦ Tip
Leave at least one piece of positive feedback per review.
Not as a softening tactic. Because if someone did something well, they should know it, the same way they should know when something is wrong. Selective attention to problems trains people to hide their work.
Receiving feedback
This is harder. Giving feedback requires skill. Receiving it requires something closer to discipline.
The first instinct when someone criticises your work is defensive. This is normal, it is biological, and it is almost always wrong to act on it. The code is not you. The decision is not your identity. The feedback is about the output, not the person. Knowing this rationally and feeling it in the moment are very different things, and the gap between them is where most feedback conversations break down.
The most useful thing you can do when receiving feedback you disagree with is to slow down. Not to concede, but to understand first. Ask what specifically concerned them. Ask what they would have done differently. You are trying to understand the model in their head, because sometimes the model is correct and you were wrong, and sometimes the model is incomplete and you can update it with information they did not have. Either outcome is useful. Neither is accessible if you close down before the conversation begins.
Separate the signal from the delivery. Feedback delivered poorly is still feedback. Someone who gives you a rough, badly phrased critique of your architecture might be right. Someone who gives you a warm, carefully worded assessment might be wrong. Do not let the packaging determine how seriously you take the content.
This is especially important early in your career, when most of the feedback you receive comes from people with more context than you. They are not always right. But the prior should be that they are, until you have enough evidence to conclude otherwise. Sitting with that discomfort is part of how you grow faster than the people around you.
Separating yourself from your work
The engineers who receive feedback best are the ones who have genuinely internalised that their code is not them. This sounds simple. It is not. Especially if you care about your work, which most good engineers do, the line between "my code has a flaw" and "I am flawed" gets blurry.
One way I have found to build this separation is to actively reframe feedback as information rather than judgement. Judgement is about you. Information is about the system. "This function has an off-by-one error" is information about the function. It tells you something actionable. It does not tell you anything about your worth as an engineer.
Another way is to notice how you talk about your code. If you find yourself saying "my implementation" and "my approach" in a way that sounds like ownership rather than authorship, watch for that. The code belongs to the codebase. You wrote it, but it is not yours to protect. Your job is to make it correct, not to defend it.
The best engineers I have worked with hold their opinions strongly and their code loosely. The worst do it the other way around.
The long game
Teams that give and receive feedback well are not always the most technically skilled. But they compound. Every honest review makes the next one easier. Every piece of criticism absorbed and acted on raises the floor. The trust required to say a hard thing and the trust required to hear one are the same trust, and it accumulates over time if you tend it carefully.
The teams I have seen stagnate are not the ones with the hardest problems. They are the ones where feedback became performance, where people said the expected thing instead of the true thing, where the gap between the meeting and the corridor conversation was too wide. Closing that gap is a leadership problem, but it is also an individual one. You cannot wait for the culture to change. You can change how you give and receive feedback starting today, and over time the people around you will follow.
Say the true thing. Hear it when it comes back. That is most of what this is.
