Skip to content
ExponaBLOG
ENGINEERING CRAFT · DAY 059 / 100

Feedback that lands: a practical Engineering Craft guide

Specific, timely and kind.

Expona Admin7 min read

Most of us have received feedback that stung, confused, or bounced off entirely. The difference between feedback that lands and feedback that gets deleted is rarely about the message—it's about how it lands. After years of code reviews, one-on-ones, and retrospectives across trading platforms, e-commerce systems, and ride-hailing services, we've learned that feedback that lands: a practical Engineering Craft guide comes down to four habits: describing behavior, explaining impact, suggesting next steps, and giving positive feedback with equal specificity.

Why feedback fails before you even speak

Feedback fails silently. A developer reads your code review comment, feels defensive, skims the rest, and files it away as "that reviewer doesn't get it." A senior engineer mentions a communication gap in a one-on-one, and the team member nods but thinks the feedback was unfair. Within a week, nothing changes.

The reason is simple: feedback without clarity and kindness activates the threat response. When someone hears criticism aimed at who they are rather than what they did, their brain goes into defend mode. They stop listening. They stop learning.

This matters because engineering is a team sport. Code reviews shape culture. One-on-ones determine retention. Retrospectives either build trust or erode it. Getting feedback right isn't nice-to-have—it's craft.

Describe the behavior, not the person

This is the hardest rule to follow and the most important. When you criticize behavior, you give someone something to change. When you criticize the person, you give them something to defend.

What doesn't work:

"You're not thinking about performance. You always ship code without profiling."

This makes it personal. It's a judgment. The developer hears "you're careless" or "you're lazy," and they're already building a counter-argument.

What works:

"I noticed this query in the user service runs in a loop over the transactions table. We measured it taking 2.4 seconds on the staging dataset. Before we merge, let's add an index or rewrite the loop."

Now you've described a specific action, shown the evidence, and made the path forward clear. The developer can engage with the feedback instead of defending themselves.

Real example from a PostgreSQL migration:

Poor: "Your migration script is sloppy. You didn't think about downtime."

Better: "This migration drops the old column in step 1 and backfills the new column in step 2. If the backfill takes longer than expected, the table will be locked. Let's add a timeout and backfill in smaller batches instead."

The second version describes the exact behavior, shows why it matters, and invites the developer to solve it together.

Explain the impact

Feedback without impact is noise. "This code is hard to read" means nothing. "Three team members asked for clarification during the code review, and the module is in the hot path where we need to move fast" means something.

Impact is the bridge between behavior and action. It answers the silent question every developer asks: "Why should I care?"

Example from a NestJS service:

You've noticed a teammate writes event handlers without error boundaries:

"In the order service, the payment event handler doesn't catch errors. Last week, when a Kafka message was malformed, the consumer crashed and we lost three minutes of order data. We need to add error handling—either retry logic or dead-letter queue routing."

That's behavior (no error handling), impact (crashed, lost data, downtime), and direction (retry or DLQ). A developer won't fight that.

Example from a React component:

Poor: "Why did you use a for loop instead of map?"

Better: "We're seeing performance issues in the customer list on slow networks. The for loop mutates the array in place, which prevents memoization. Using map creates a new reference, so memoization works and we avoid re-renders."

Same feedback, but now the developer understands the why. They're more likely to apply it to future code too.

Suggest a concrete next step

Vague feedback is demoralizing. "This needs to be better" leaves the developer guessing. A concrete next step shows you've thought about the solution and you're invested in their growth.

Weak next steps:

  • "Think about error handling."
  • "This could be more scalable."
  • "Look at the database design again."

These are directions without a destination. The developer nods, but they don't know where to start.

Concrete next steps:

  • "Add a try-catch around the Kafka consumer and emit failed messages to a dead-letter topic. Here's a reference implementation from the payment service."
  • "Right now we're fetching all user preferences on login. Let's lazy-load them instead—fetch only what the current page needs. I've started a branch at feature/lazy-prefs."
  • "This migration queues up all rows at once. Let's add pagination and process them in batches of 1000. That way we won't lock the table if the operation takes 20 minutes."

Each one gives a specific action, often with a reference or starting point. A developer can follow it immediately.

Code example—Redis caching without specificity:

typescript
// Weak feedback: "Cache this better."

async function getUserMetrics(userId: string) {
  const cached = await redis.get(`user:${userId}:metrics`);
  if (cached) return JSON.parse(cached);
  
  const metrics = await db.query(`SELECT * FROM metrics WHERE user_id = ?`, [userId]);
  return metrics;
}

Concrete feedback with next step:

"This endpoint is hit 200 times per second during peak hours. Right now we're fetching from the database even on cache miss. Let's add a short TTL for misses too, so we don't hammer the database. Change the logic to: if cache.get returns null, set a 5-second TTL on a 'null' marker. Here's how other services do it: [link]. This should cut DB load by 60%."

Now the developer knows exactly what to do and why it matters.

Give positive feedback just as specifically

This is where most teams fail. Positive feedback gets mumbled: "Good job," "Nice work," "Looking good." Because it's easy to dismiss, it doesn't reinforce behavior. The developer doesn't know which habit to repeat.

Specific positive feedback is a management tool. It shapes culture by showing what good looks like.

Vague positive feedback:

  • "Great pull request."
  • "Thanks for the help in the code review."
  • "Nice error handling."

Specific positive feedback:

  • "Your error handling in the payment retry logic is a pattern we should use elsewhere. You caught the rate-limit case and the timeout case separately, then logged each with different context. That made it easy for me to debug when a test failed."
  • "In this code review, you asked about the migration window and suggested batching. That question caught a real production risk. Do more of that."
  • "The way you documented the Redis TTL strategy saved us from a support ticket. Three team members referenced your comment in the next sprint."

Each one describes what they did, why it mattered, and implicitly asks them to do it again.

Common mistakes

Mistake 1: Sandwich feedback with praise. "Great code, but here's the issue, great effort anyway." This feels patronizing. The developer knows the real message is the middle part, and the praise cheapens the feedback. Just describe the behavior and impact directly.

Mistake 2: Feedback as a teaching moment in a group setting. "Let me explain how everyone should handle this case..." You're right, but the person who made the mistake feels called out in front of peers. Do it one-on-one or in a private channel. Public feedback should be positive and specific.

Mistake 3: Waiting too long. Feedback loses potency over time. If you notice a behavior on Monday, say something by Wednesday. After a week, it feels like you've been sitting on judgment.

Mistake 4: Assuming intent. "You didn't think about this" or "You ignored the design doc." You don't know why. They might have missed it, or had a constraint you weren't aware of. Say what you observed, not what you think they intended.

Mistake 5: Feedback without follow-up. You give feedback, the developer acts on it, and you never acknowledge it. They're left wondering if it was useful. Circle back. "I saw you batched the migration. That worked—load times improved by 40%. That's the pattern we want going forward."

Key takeaways

  • Describe the specific behavior you observed, not a judgment about the person. Replace "You're not thinking about performance" with "This query runs in a loop and takes 2.4 seconds."
  • Always explain impact. Show why the behavior matters to the team, the system, or the customer. Impact is what makes feedback stick.
  • Suggest a concrete next step. "Try this approach," "Add a timeout here," "Use memoization instead." Remove the guesswork.
  • Give positive feedback with the same specificity. "You did X, which helped the team by Y" reinforces behavior better than "good job."
  • Deliver feedback soon, in private, and without assuming intent. Speed, privacy, and humility make feedback safe to receive.
  • Follow up after the person acts on feedback. A simple "I noticed you fixed this—it's better" closes the loop and builds trust.

Feedback that lands isn't about being nice or being harsh. It's about being clear, specific, and human. It treats the person as someone who wants to improve and deserves to know exactly how.

ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles