Art, culture, and the conversations that matter.

Category: Default (page 4 of 12)

The Interview Gauntlet: Why We Test for Everything Except the Job

Let me set the scene. You’ve been writing code for ten years. You’ve shipped features that millions of people use. You’ve debugged race conditions at 2 a.m. while a VP breathed down your neck. You’ve turned spaghetti into something a human can actually read. Then you apply for a new role, and the first thing they ask is to invert a binary tree on a whiteboard while three strangers stare at you like you’re a zoo animal that’s supposed to do a trick.

I’m Fritz Muller, and I’ve sat on both sides of the hiring table enough times to know that most tech interviews are a masterclass in missing the point. We’ve built an entire industry ritual around testing for anything except the actual job. It’s not just broken—it’s a cargo cult with a LinkedIn presence.

The Whiteboard Is a Stage, Not a Workbench

Here’s the thing: nobody—and I mean nobody—stands at a whiteboard and reimplements depth-first search from memory on a Tuesday afternoon. That’s not how software gets built. Real engineering happens in an IDE, with documentation tabs open, Stack Overflow within reach, and a half-eaten sandwich slowly congealing next to the keyboard. Yet we’ve decided that the pinnacle of candidate evaluation is watching someone sweat through a contrived algorithm puzzle while three interviewers silently judge their handwriting.

This isn’t a skills assessment. It’s a performance. And like most performances, it rewards a very specific type of person: someone who’s spent months grinding LeetCode, not someone who’s spent years building maintainable systems. I’ve seen brilliant infrastructure engineers bomb these interviews because they haven’t memorized the exact syntax for a heap in a language they haven’t touched since college. Meanwhile, the candidate who aces it might not know how to set up a CI pipeline or write a design doc to save their life.

The whiteboard interview tests for whiteboard interviewing. That’s it. It’s a self-licking ice cream cone of a process.

Person standing at whiteboard with marker, looking confused

Take-Home Projects: The Unpaid Overtime Trap

Then there’s the other extreme: the take-home assignment. On the surface, it seems more reasonable. “Build a small REST API that does X.” Sounds fine, right? Until you realize X requires setting up a database, writing migrations, handling authentication edge cases, and producing documentation that would make a technical writer weep. The company says it should take “4-6 hours.” It takes 20. And you’re doing it after your actual job, on a weekend, while your family wonders why you’re voluntarily working for free.

I once got a take-home that asked me to build a miniature version of their core product. Not a toy problem—a miniature version. I spent 15 hours on it, submitted a working solution with tests and a README, and then got a form rejection two weeks later with no feedback. I’d effectively done a sprint’s worth of work for a company that couldn’t be bothered to spend 15 minutes telling me why they passed. That’s not an interview; that’s exploitation with a smiley face in the email footer.

And here’s the kicker: take-homes don’t even simulate the job well. On the job, you’d have access to the existing codebase, teammates to bounce ideas off, and a product manager to clarify requirements. A take-home gives you none of that. It’s a solo marathon in a vacuum, which is the exact opposite of how healthy engineering teams operate.

The Culture Fit Charade

Then we get to the “culture fit” interview, which is often code for “do I personally like this person in 45 minutes or less?” It’s the most subjective part of the process, dressed up in behavioral questions that are supposed to be objective. “Tell me about a time you disagreed with a coworker.” What they’re really asking is: “Will you make waves, or will you quietly absorb whatever nonsense we throw at you?”

I’ve seen culture fit used to filter out perfectly qualified engineers who didn’t laugh at the interviewer’s jokes, or who came across as too direct, or who—god forbid—wore a band t-shirt instead of a startup-approved hoodie. It’s a vibe check masquerading as a values alignment assessment. And it’s often the tiebreaker that sinks candidates who would have actually improved the team’s culture by bringing something different to it.

Real culture fit isn’t about whether you’d want to grab a beer with someone. It’s about whether they share your team’s core principles around code quality, collaboration, and user focus. You can’t measure that with a few canned questions. You measure it by working together on something real.

Two people having a tense conversation in a modern office

The Resume Black Hole and Keyword Bingo

Before you even get to the interviews, you have to survive the resume screen. This is where your carefully crafted summary of real accomplishments gets fed into an applicant tracking system that’s looking for the word “Kubernetes” exactly seven times. You could have single-handedly migrated a Fortune 500 company off bare metal, but if you wrote “container orchestration” instead of “K8s,” you’re invisible.

Recruiters—bless their overworked hearts—often don’t have the technical context to evaluate resumes deeply. So they rely on keyword matching and pedigree signals. FAANG experience? Check. Stanford CS degree? Check. Actually built and maintained the thing the job requires? Eh, maybe, if the keywords line up. It’s a system that optimizes for people who are good at writing resumes, not people who are good at engineering.

I’ve reviewed resumes where the candidate listed “Led migration of 50 microservices to new infrastructure” as a bullet point. That’s a massive, complex project. But it got buried under someone else’s “Proficient in Java, Python, Go, Rust, C++, and Kubernetes.” The second person might have done a hello-world in each. The first person kept a business running. Guess who got the call.

What We Should Be Testing Instead

So if all these methods are broken, what’s the alternative? It’s not rocket science. It’s just testing for the job.

1. Paid, Time-Boxed Work Trials

Give the candidate a real, scoped task from your backlog—something small but representative. Pay them for their time. Let them use the tools they’d use on the job. Pair them with a future teammate. Watch how they navigate ambiguity, ask questions, and actually produce working code. This isn’t a new idea; companies like Automattic and Basecamp have done it for years. It works because it’s not a simulation. It is the job.

Yes, this requires more coordination than a whiteboard session. Yes, it costs money. But compare that to the cost of a bad hire—the months of ramp-up, the team morale hit, the eventual firing and rehiring. A paid trial is cheap insurance.

2. Code Reviews Instead of Code Writing

Most senior engineers spend more time reviewing code than writing greenfield algorithms. So why not test that? Give the candidate a pull request with subtle bugs, poor structure, and missing tests. Ask them to review it. You’ll learn more about their engineering judgment in 30 minutes than you would in three hours of whiteboard puzzles. Can they spot the race condition? Do they suggest meaningful improvements? Do they communicate feedback clearly and kindly? That’s the job.

3. System Design That’s Actually About Tradeoffs

System design interviews often devolve into architecture astronautics—drawing boxes and arrows for a hypothetical Twitter clone that needs to handle a billion users. But real system design is about tradeoffs given constraints. So give them constraints: a specific budget, a specific team size, a specific legacy system they have to integrate with. Ask them what they’d cut first. The best engineers don’t build ivory towers; they build things that work within messy reality.

Two developers collaborating at a desk with laptops and notes

4. Behavioral Questions That Aren’t Bullshit

Instead of “tell me about a time you failed,” ask “walk me through the last production incident you handled.” That’s a real story. You’ll hear about their debugging process, how they communicate under pressure, whether they blame others or take ownership. You’ll learn if they actually understand the systems they worked on. And you won’t get a rehearsed STAR-format monologue about a “failure” that was secretly a humblebrag.

The Ego Problem

Let’s address the elephant in the room: a lot of these bad practices persist because they feed interviewer egos. The whiteboard gauntlet lets someone feel smart by stumping candidates with a puzzle they themselves just learned the answer to last week. The grueling multi-round process signals that the company is “elite” and “hard to get into,” which strokes the collective ego of everyone who already made it through.

I’ve sat in debrief sessions where an interviewer rejected a candidate because “they didn’t solve the problem the way I would have.” Not that the solution was wrong—it was just different. That’s not evaluating competence; that’s enforcing intellectual conformity. And it’s a fantastic way to build a team of clones who all think alike and miss the same blind spots.

Hiring should be a humbling process. You’re trying to find people who are better than you in some dimension, who will challenge your assumptions and make the team stronger. If your process is designed to make you feel superior, you’re doing it wrong.

The Diversity Tax

These broken processes don’t just annoy everyone—they systematically filter out certain groups. Candidates who can’t afford to take unpaid time off for marathon take-homes. Candidates who didn’t attend a university with a LeetCode grinding culture. Candidates who communicate differently, whether due to neurodivergence, cultural background, or just not being a smooth-talking extrovert.

When your process tests for whiteboard performance and cultural sameness, you’re not getting “the best.” You’re getting a narrow slice of people who are good at your specific hazing ritual. And then you wonder why your team struggles with blind spots and groupthink.

What Candidates Can Do (Besides Suffer)

If you’re on the job market right now, you’re probably nodding along with a mix of recognition and despair. The system is stacked against you, and you can’t single-handedly reform it. But you can make strategic choices:

  • Ask about the process upfront. If a company can’t clearly explain their interview stages and what each one tests for, that’s a red flag. A good process is transparent and relevant.
  • Push back on unreasonable take-homes. “I’m excited about this role, but this assignment seems larger than the 4-hour estimate. Could we scope it down or discuss a paid trial instead?” Some companies will negotiate. The ones that won’t are telling you something.
  • Treat the interview as a two-way evaluation. You’re also deciding if you want to work there. If the process feels disrespectful or disconnected from reality, imagine what the job will be like.

FAQ: Because You’re Probably Still Fuming

Are whiteboard interviews ever useful?

In very specific contexts—like evaluating a new grad’s fundamental CS knowledge—a short, straightforward algorithm question can be fine. But it should be a small part of the process, not the main event. And it should never involve esoteric data structures that nobody uses in production. If you’re asking a senior engineer to reimplement a red-black tree, you’ve lost the plot.

What if my company can’t afford paid work trials?

If you can’t afford to pay a candidate for a few hours of work, you probably can’t afford to hire them full-time. But if budget is genuinely tight, consider a shorter, more focused pair-programming session on a real (but small) problem. The key is to make it collaborative and representative, not a solo exam. And always respect the candidate’s time—don’t ask for more than 2-3 hours total across all stages.

How do I convince my team to change our hiring process?

Start with data. Track how your current process correlates with on-the-job performance. (Spoiler: it probably doesn’t.) Share case studies from companies that have moved to work-sample testing. Propose a low-risk experiment: for the next three hires, add a paid trial stage and compare the results. Nothing changes minds faster than seeing a great candidate who would have been rejected under the old system thrive in the new one.

Isn’t this just complaining? What’s the real solution?

The real solution is for engineering leaders to treat hiring as a design problem with the same rigor they’d apply to a distributed system. Define what “good” looks like for the role. Design a process that measures those specific things. Test the process itself—run candidates you already know are good through it and see if it identifies them correctly. Iterate. Most companies spend more time choosing office furniture than designing their interviews. That’s the root cause.

When the dust settles and you’re staring at yet another rejection email that makes no sense, remember that the problem isn’t you. It’s an industry that’s optimized its hiring for everything except competence. And until we start treating the interview process itself as a system worth engineering, we’ll keep getting exactly the results we deserve.

The Hiring Gauntlet: Why Your Dev Interview Tests for the Wrong Species

Let’s be real: most developer hiring processes are a circus. Not the fun kind with popcorn and a guy on stilts, but the kind where you’re asked to juggle flaming swords while reciting the Fibonacci sequence backward—only to land a job where 90% of your time goes to untangling a decade-old CSS file named final_v2_REALFINAL.css. The problem isn’t that companies are picky. It’s that they’re picky about the wrong damn things. They test for trivia, not temperament. They screen for puzzle-solving, not the ability to sit through a three-hour meeting about button colors without setting the conference room on fire. The hiring gauntlet has become a bizarre ritual that filters for a very specific subspecies of human—one that thrives on whiteboard algorithms and has never once had to explain to a project manager why “just adding a button” touches seventeen microservices.

I’ve been on both sides of this table. I’ve watched brilliant engineers get rejected because they couldn’t invert a binary tree on command. I’ve seen companies hire people who aced every LeetCode hard but couldn’t write a coherent commit message if their life depended on it. The mismatch is so glaring it’s almost funny—except it’s not, because it wastes everyone’s time and produces teams that are technically dazzling but operationally dysfunctional. The real job of a software developer isn’t solving isolated puzzles under a stopwatch. It’s navigating ambiguity, communicating with humans who don’t speak JSON, and resisting the urge to rewrite the entire codebase every sprint. So why do we keep testing for the wrong things?

Person staring at a whiteboard filled with complex diagrams, looking overwhelmed

The Whiteboard Theater

Picture this: you’re in a room with three engineers, a whiteboard, and a marker that’s running out of ink. They ask you to design a URL-shortening service. You have thirty minutes. Go. This is the classic whiteboard interview, and it’s about as relevant to actual software development as a cooking competition is to running a restaurant kitchen. In a real kitchen, nobody asks you to whip up a soufflé while a panel of chefs stares at you in silence. You’re dealing with orders flying in, a fryer that’s acting up, and a line cook who’s having a bad day. The job is coordination, adaptation, and not burning the place down. Yet in tech, we’ve decided the best way to assess a developer is to isolate them from every tool and teammate they’d normally lean on, then demand a performance of pure algorithmic recall.

This theater selects for one very specific trait: the ability to perform under artificial stress while regurgitating computer science fundamentals. It does not select for the ability to debug a race condition in production at 2 a.m., or to gently tell a junior developer that their pull request is a crime against readability, or to sit through a sprint planning meeting without visibly losing the will to live. The whiteboard gauntlet is a hazing ritual dressed up as evaluation. It tells you almost nothing about how someone will actually behave when faced with the messy, ambiguous, human-infested reality of building software.

The Take-Home Project That Ate My Weekend

Then there’s the other extreme: the take-home assignment. In theory, it’s better. You get to use your own tools, work at your own pace, and produce something that resembles real work. In practice, it’s often a trap. The assignment is vaguely specified, expected to take “four to six hours,” but actually requires building a miniature version of Netflix with a custom recommendation engine and full test coverage. Candidates with families, side projects, or a healthy desire to not spend their entire weekend working for free are immediately disadvantaged. The process selects for people who have nothing else going on—or who are willing to sacrifice everything else to impress a company they don’t even work for yet.

Even when the scope is reasonable, the evaluation criteria are often opaque. You submit your code and get a rejection email with no feedback, or worse, feedback that nitpicks your choice of variable names while ignoring the fact that you actually solved the problem. The take-home project becomes a black box where you pour hours of unpaid labor, and the company pours your code into a shredder labeled “culture fit.” It’s not a skills assessment; it’s a test of how much free work you’ll tolerate before you’ve even signed an offer letter. And that’s a dangerous precedent to set.

Person working late at night on a laptop, looking tired and frustrated

The Trivia Gauntlet: Name That Framework

Some interviews skip the performance art and go straight for the pub quiz. “What’s the difference between let and var in JavaScript?” “Explain the event loop.” “What’s the time complexity of quicksort in the worst case?” These questions have answers you can memorize in an afternoon. They test recall, not reasoning. They favor candidates who’ve spent hours cramming interview prep sites over those who’ve spent years building and maintaining actual systems. Knowing the exact Big-O notation of an algorithm you’ll never implement from scratch is not a predictor of job performance. It’s a predictor of how recently you read Cracking the Coding Interview.

The trivia approach also introduces a nasty bias: it rewards people who are good at taking tests and have the leisure time to study. It punishes experienced developers who’ve been too busy shipping code to keep a mental index of every sorting algorithm’s space complexity. The result is a workforce that looks great on paper but struggles when faced with the kind of problem that doesn’t have a single correct answer—which is to say, every real problem.

The Real Job: A Taxonomy of Actual Developer Work

Let’s talk about what developers actually do all day. If you’ve never worked in software, you might imagine it’s a lot of typing code in a dark room while listening to lo-fi beats. The reality is more like: reading other people’s code and trying to figure out what hallucinogenic substance they were on when they wrote it; sitting in meetings where the phrase “just a small change” is uttered with a straight face; writing documentation that no one will read until something breaks; reviewing pull requests that are either three lines or three thousand lines, with no in-between; and debugging issues that only occur on the third Tuesday of the month when the server room is slightly too humid.

None of this is tested in a typical interview. You won’t be asked to navigate a legacy codebase where the original author left the company five years ago and took all the context with them. You won’t be asked to explain a technical decision to a non-technical stakeholder who thinks “the cloud” is a literal weather phenomenon. You won’t be asked to pair-program with someone who has strong opinions about tabs versus spaces and is willing to die on that hill. Yet these are the skills that determine whether a team functions or implodes. The ability to invert a binary tree is, by comparison, a party trick.

Two developers collaborating at a desk, one pointing at the screen while the other listens

What We Should Be Testing Instead

If the goal is to hire people who will actually succeed at the job, the interview needs to resemble the job. That means collaborative problem-solving, not solo performance. Give the candidate a real, messy codebase—maybe even a slice of your actual production code with the sensitive bits scrubbed—and ask them to add a feature or fix a bug. Pair them with a future teammate. Watch how they ask questions, how they handle not knowing something, how they react when the test suite fails for a reason that has nothing to do with their change. That’s the data you need.

Test for communication. Ask the candidate to explain a technical concept to someone who isn’t technical. It doesn’t have to be a formal presentation; just a conversation. Can they adjust their language based on the listener? Do they get impatient? Do they default to jargon as a shield? The ability to translate between the world of machines and the world of humans is one of the most undervalued skills in this industry, and it’s almost never assessed.

Test for code review skills. Give them a pull request filled with subtle issues—not syntax errors, but design flaws, security holes, maintainability nightmares. See what they catch and how they communicate their feedback. Are they constructive or dismissive? Do they focus on what matters or nitpick formatting? A good code reviewer saves a team from countless future headaches. A bad one creates a culture of fear and resentment.

Test for debugging. Not the “find the missing semicolon” kind, but the kind where the bug is a symptom of a deeper architectural problem. Give them logs, metrics, and access to a running system. See if they can trace the issue back to its root cause without randomly changing things until something works. Debugging is detective work, and it requires a mindset that’s completely different from writing algorithms from scratch.

The Culture Fit Trap

“Culture fit” is often code for “people who are like us.” It’s a vague, subjective criterion that gets wielded to reject candidates who don’t share the interviewer’s hobbies, background, or communication style. Real culture add—bringing in people who expand the team’s perspectives and capabilities—is what healthy organizations need. But that requires defining what your engineering culture actually values. Is it blameless postmortems? Is it continuous learning? Is it the ability to disagree without being disagreeable? If you can’t articulate that, you’re not assessing culture fit; you’re assessing whether you’d want to grab a beer with the person. And that’s a lousy way to build a team.

Instead, define the behaviors that make someone effective in your specific environment. Maybe it’s the willingness to document decisions. Maybe it’s the habit of asking “what problem are we solving?” before diving into code. Maybe it’s the discipline to leave the codebase better than they found it. Then design interview steps that probe for those behaviors. It’s harder than printing out a list of algorithm questions, but it’s also harder to end up with a team of brilliant jerks who can’t collaborate.

The Pipeline Problem

Part of the dysfunction comes from how hiring pipelines are built. Recruiters, who often don’t have a technical background, are given a checklist of keywords and told to screen resumes. Hiring managers, who are overworked and under pressure to fill seats, default to the interview formats they experienced themselves—formats that were never validated but have achieved the status of tradition. The result is a self-perpetuating cycle of bad assessment. People who are good at whiteboard interviews get hired, they become interviewers, and they design whiteboard interviews because that’s what they know. The process evolves to select for the process itself, not for the job.

Breaking this cycle requires intentional effort. Someone has to look at the data—are the people who pass our interviews actually performing well on the job? If not, the interview is the problem, not the candidates. This kind of introspection is rare because it’s uncomfortable. It might reveal that your “rigorous” hiring bar is just a fancy filter for people who are good at taking tests. It might reveal that you’ve been rejecting perfectly capable engineers for reasons that have nothing to do with their ability to do the work. And that’s a hard pill to swallow when you’ve built your professional identity around being a gatekeeper of excellence.

FAQ: Because You Probably Have Questions

1. Aren’t algorithm questions important for testing problem-solving ability?

They test a very narrow slice of problem-solving: the ability to solve well-defined, abstract puzzles under time pressure. Real software problems are rarely well-defined, almost never abstract, and the time pressure is usually self-inflicted by poor planning. Algorithm questions aren’t useless, but they’re wildly over-weighted. If you want to test problem-solving, give the candidate a real, messy problem from your actual domain and see how they approach it. That’s a much richer signal.

2. What if we need to hire quickly and don’t have time for elaborate simulations?

Speed is often the excuse for lazy hiring, but it’s a false economy. A bad hire costs far more time than a thorough interview process. Even a compressed process can be designed to test job-relevant skills: a one-hour pair-programming session on a real task, a thirty-minute discussion of a past project the candidate worked on, and a quick review of a code sample they provide. That’s three hours total, and it tells you more than a day of whiteboard puzzles.

3. How do we evaluate soft skills without being subjective?

Define what “soft skills” mean in your context. If it’s communication, give them a specific communication task and evaluate the outcome against a rubric. If it’s collaboration, have them work with someone and observe specific behaviors: do they ask questions? do they listen? do they incorporate feedback? Subjectivity creeps in when you evaluate based on vague impressions. Rubrics and structured observation push back against that.

4. Should we just stop doing technical interviews altogether?

No, but you should stop doing bad technical interviews. The goal isn’t to lower standards; it’s to make the standards relevant. A good technical interview tests the skills the job actually requires. If your job requires deep algorithm knowledge, test that. If it requires debugging distributed systems, test that. If it requires refactoring spaghetti code without breaking everything, test that. The problem isn’t technical rigor—it’s rigor applied to the wrong domain.

The Bottom Line

Hiring is hard. It’s messy, it’s time-consuming, and there’s no perfect method. But the current standard—a gauntlet of trivia, puzzles, and performances—is optimized for the wrong outcome. It’s optimized for making interviewers feel smart and for filtering candidates in a way that’s easy to defend bureaucratically. It is not optimized for finding people who will write maintainable code, mentor junior developers, communicate with stakeholders, and keep their heads when the production database goes down on a Friday evening.

If you’re involved in hiring, ask yourself: does this interview question actually measure something that matters for the job? If the answer is “well, it shows they’re smart,” dig deeper. Smart is abundant. The ability to apply smartness to the actual, grinding, collaborative work of software development is what’s scarce. Test for that. Your team—and your sanity—will thank you.

The Problem With Hiring Processes That Test for Everything Except the Actual Job

Let’s call it what it is: most tech hiring is a circus. Not the fun kind with popcorn and acrobats, but the kind where you’re asked to juggle flaming data structures while reciting the Big O complexity of an algorithm you haven’t touched since sophomore year. The problem isn’t that companies want good engineers. The problem is they’ve built entire rituals around testing skills that have nothing to do with the job. Then they act surprised when the new hire can invert a binary tree on a whiteboard but can’t ship a feature without someone holding their hand.

I’ve been on both sides of this mess. As an interviewer, I’ve watched candidates sweat through logic puzzles ripped from a math Olympiad. As a candidate, I’ve been asked to design a distributed system in 45 minutes for a role that was 90% CRUD apps and CSS tweaks. The gap between the test and the work is so wide you could drive a Kubernetes cluster through it.

The Whiteboard Theater

Picture this: a small, windowless room. A marker that’s running dry. An interviewer who hasn’t glanced at your resume since HR forwarded it three weeks ago. You’re told to reverse a linked list. On a whiteboard. In 20 minutes. While they watch.

This is the whiteboard theater, and it’s the worst kind of improv. The issue isn’t that linked lists are useless—they’re fundamental. The issue is that the performance has nothing to do with the job. Real engineering doesn’t happen in a silent room with a stranger staring at your back. It happens in a messy IDE, with Stack Overflow tabs open, a linter yelling at you, and a colleague saying, “Wait, why are we doing this at all?”

Whiteboard interviews test for anxiety management, not engineering skill. They favor people who can memorize algorithm flashcards and perform under pressure. That’s a great filter if you’re hiring for a competitive programming team. It’s a terrible filter if you’re hiring someone to debug a race condition in your payment pipeline at 2 a.m.

Person writing on whiteboard with marker

The Take-Home Project That Ate My Weekend

Then there’s the other extreme: the take-home project. “It should only take 4 hours,” they say. It takes 20. You’re building a mini-application from scratch, with a frontend, backend, database, and a README that explains your architectural decisions. You’re doing this for free, on your own time, while juggling your current job and maybe a family.

Here’s the kicker: half the time, nobody even reads your README. They glance at the code, run it once, and if it doesn’t crash, you move to the next round. The project is often a thinly veiled attempt to get free labor—I’ve seen companies use candidate submissions as prototypes for internal tools. Even when that’s not the case, the asymmetry is absurd. You invest a weekend; they invest 15 minutes.

And what does the project actually test? Your ability to work in isolation, with perfect requirements, no interruptions, and no collaboration. That’s not engineering. That’s a homework assignment.

The Culture Fit Charade

Then comes the “culture fit” interview. This is where things get truly unhinged. You’re asked what animal you’d be, or how many golf balls fit in a school bus. The subtext is: “Are you like us?” Which usually means: “Do you share our unexamined biases and willingness to work weekends?”

Culture fit has become a euphemism for homogeneity. It’s not about whether you can contribute to a team’s dynamic—it’s about whether you’ll disrupt the fragile equilibrium of people who’ve never had their assumptions challenged. Real culture add is what moves teams forward. Culture fit keeps them stuck.

I once sat through an interview where the CEO asked me to name my favorite text editor. I said VS Code. He frowned and said, “We’re a Vim shop.” I didn’t get the job. I later found out their “engineering culture” was a single Vim-obsessed lead who wrote unreadable Perl scripts and refused to document anything. Bullet dodged.

The Real Job: What We Should Be Testing For

Let’s get concrete. What does a typical software engineering job actually involve?

  • Reading and understanding existing code—often bad, poorly documented code written by someone who left the company two years ago.
  • Debugging production issues under time pressure, with incomplete logs and a customer screaming in a Slack channel.
  • Reviewing other people’s code and giving feedback that is honest but not soul-crushing.
  • Writing code that other humans can read, modify, and delete without wanting to quit.
  • Communicating technical trade-offs to non-technical stakeholders without making them feel stupid.
  • Navigating legacy systems, technical debt, and the accumulated decisions of people who meant well but were in a hurry.

Notice what’s missing? Inverting a binary tree. Implementing quicksort from memory. Designing a parking lot in 45 minutes. These are party tricks. They don’t tell you if someone can ship a feature, fix a bug, or improve a process.

Two people collaborating on code at a desk

What Good Hiring Looks Like

Good hiring processes are rare, but they exist. They look less like a hazing ritual and more like a day of work. Here’s what I’ve seen work:

Paired Programming on Real Code

Give the candidate a real, non-critical task from your backlog. Pair them with a future teammate. Watch how they navigate the codebase, ask questions, and handle getting stuck. This tests collaboration, code literacy, and problem-solving—all at once.

Debugging Simulations

Set up a broken environment—a failing test, a misconfigured service, a mysterious error log. Give the candidate access to the tools they’d actually use. See if they can find the root cause. This is infinitely more predictive than a whiteboard algorithm.

Code Review Exercises

Hand them a pull request full of subtle issues: security holes, performance traps, readability nightmares. Ask them to review it. You’ll learn about their attention to detail, their communication style, and whether they’re the kind of person who leaves helpful comments or just writes “LGTM.”

System Design With Context

Instead of “design Twitter,” give them a problem your team actually faced. Explain the constraints, the trade-offs you debated, the ugly parts you had to accept. See if they ask good questions. See if they can think in terms of cost, complexity, and maintainability—not just theoretical scalability.

The Meta-Problem: Hiring as a Proxy for Engineering Culture

Here’s the uncomfortable truth: bad hiring processes are a symptom of bad engineering culture. When a team doesn’t know what good engineering looks like, they can’t design an interview to find it. So they copy what Google did in 2008, or they cargo-cult the latest fad from a tech influencer’s Twitter thread.

Engineering culture is the set of unspoken rules about how work gets done. It’s how decisions are made, how mistakes are handled, how credit is shared. A team with a healthy culture knows what skills they actually need. They hire for those skills. A team with a toxic culture hires for compliance, for ego, for the ability to suffer silently.

The hiring process is a mirror. If your interviews are a gauntlet of trivia and trick questions, your culture probably values looking smart over being effective. If your interviews are a series of monologues where the candidate barely speaks, your culture probably doesn’t listen to anyone. If your interviews are disorganized and disrespectful of the candidate’s time, your culture probably treats engineers as interchangeable parts.

Why Companies Cling to Broken Processes

If these processes are so obviously flawed, why do they persist? A few reasons:

Fear of false positives. Companies are terrified of hiring the wrong person. So they design processes that minimize false positives at any cost—even if it means rejecting tons of great candidates. It’s easier to say “we only hire the top 1%” than to admit your process is random.

Cargo culting. “Google does brainteasers, so we should too.” Never mind that Google publicly admitted brainteasers were useless and stopped using them over a decade ago. The meme outlives the evidence.

Interviewer ego. Some interviewers treat the process as a chance to prove how smart they are. They ask obscure questions, nitpick irrelevant details, and reject candidates who don’t share their specific technical religion. It’s not about finding a great colleague—it’s about validating their own expertise.

Lack of training. Most companies spend zero time teaching people how to interview. They throw engineers into rooms with candidates and say “assess their technical skills.” The result is a random walk through whatever the interviewer happens to care about that day.

What Candidates Can Do

If you’re on the job market, you can’t fix a company’s broken hiring process. But you can protect your time and sanity.

Ask about the process upfront. Before you agree to a technical screen, ask what it involves. If it’s a whiteboard algorithm gauntlet for a role that’s mostly debugging and feature work, politely push back. Some companies are flexible; some aren’t. Either way, you’ll know what you’re signing up for.

Treat the interview as a two-way street. You’re evaluating them as much as they’re evaluating you. Ask about their engineering culture. Ask how they handle technical debt, how they make architectural decisions, how they onboard new hires. If they can’t answer coherently, that’s a signal.

Set boundaries on take-home work. If a project is supposed to take 4 hours, spend 4 hours. Submit what you have. If they reject you because you didn’t spend 20 hours, you’ve dodged a bullet. Companies that respect boundaries in the interview process are more likely to respect them on the job.

Remember that rejection is not a reflection of your skill. Most hiring processes are so noisy that getting rejected tells you almost nothing. It could mean you’re not a fit. It could mean the interviewer had a bad day. It could mean the company doesn’t know what it’s looking for. Don’t internalize it.

Person working on laptop with coffee

What Companies Can Do

If you’re in a position to influence hiring at your company, start by asking: What do we actually need people to do? Then design your process backward from that.

Audit your current process. Look at the last 10 hires. Which interview stages actually predicted on-the-job performance? Which ones were just theater? Kill the theater.

Train your interviewers. Teach them how to assess skills, not just how to ask questions. Teach them about unconscious bias, about structured interviewing, about the difference between a signal and noise.

Standardize, but don’t rigidify. Every candidate should get a fair, consistent process. But that doesn’t mean every interview should be identical. Leave room for interviewers to dig into a candidate’s specific strengths.

Respect the candidate’s time. If you’re asking for a take-home project, pay them for it. If you can’t pay them, keep it short—really short. A 2-hour exercise that mimics real work is more predictive and more respectful than a 20-hour monster.

Hire for growth, not just current skill. The best engineers I’ve worked with weren’t necessarily the ones who aced the interview. They were the ones who learned fastest on the job. Curiosity, humility, and a willingness to be wrong are superpowers. Test for those.

The Bottom Line

Hiring is hard. There’s no perfect process. But there’s a clear difference between processes that try to approximate the actual job and processes that have drifted into self-parody. If your interview tests skills that nobody on your team uses, you’re not hiring engineers. You’re running a trivia night with higher stakes.

Stop asking candidates to juggle. Start asking them to do the job. You might be surprised who actually shows up.

FAQ

Why do so many companies still use whiteboard algorithm interviews?
Because they’re easy to standardize and grade. A binary tree inversion has a right answer. Debugging a real system doesn’t. Companies often optimize for process consistency over predictive validity, and whiteboard interviews are the ultimate checkbox exercise.

What’s the best way to assess a candidate’s debugging skills?
Give them a broken environment—a failing test suite, a misconfigured service, a production-like error log—and watch them work. Provide the tools they’d actually use on the job. Pay attention to how they form hypotheses, how they isolate variables, and whether they ask for help when stuck. That’s debugging. Not reversing a linked list on a whiteboard.

How can I tell if a company’s engineering culture is healthy before I accept an offer?
Ask specific questions during the interview: “How do you handle incidents?” “Can you walk me through the last architectural decision the team debated?” “How is technical debt managed?” Vague, glossy answers are a red flag. Also, pay attention to how the interviewers treat each other—if they interrupt, dismiss, or one-up each other in front of you, that’s the culture you’ll be joining.

Your Hiring Process Is a Circus, and You’re the Clown

I’ve been on both sides of the hiring table enough times to know that most tech interviews are a circus. Not the fun kind with acrobats and cotton candy, but the kind where you’re asked to juggle flaming binary trees while three strangers stare at the back of your head. The problem isn’t that companies want to filter candidates—it’s that they’ve built an entire priesthood around filtering for the wrong things. And we all just nod along like it makes sense.

Here’s the blunt truth: if your hiring process tests for skills nobody uses on the job, you’re not hiring engineers. You’re hiring professional interviewees. Those are two very different species, and one of them is terrible at shipping software.

The Whiteboard Industrial Complex

Let’s start with the most obvious offender. You know the scene. A candidate walks into a room, gets handed a dry-erase marker, and is told to invert a binary tree on the spot. No syntax highlighting. No autocomplete. No way to run the damn code. Just a grown adult scribbling pseudocode while three people watch in silence, occasionally jotting notes that probably say “nervous” or “didn’t explain Big O fast enough.”

I’ve been that candidate. I’ve also been the interviewer who had to pretend this was a valid way to assess someone’s ability to build production software. It’s not. It’s a hazing ritual dressed up as rigor. The only thing it reliably measures is how well someone performs under artificial, high-anxiety conditions that have nothing to do with the actual work. When was the last time you fixed a production outage by standing at a whiteboard with no access to documentation, Stack Overflow, or even a linter? Never. Because that’s not how engineering works. We debug with tools. We refactor with tests. We design with feedback loops. The whiteboard gauntlet filters for people who’ve memorized algorithm textbooks, not people who can ship maintainable code. It’s a theater of competence, and the audience is just as trapped as the performer.

Person writing on a whiteboard during a meeting

The Take-Home Project That Eats Your Weekend

Then there’s the other extreme: the take-home assignment. On paper, it sounds reasonable. “Build a small REST API that does X.” But in practice, it’s a black hole. The spec is always just vague enough that you spend twelve hours over-engineering it, because you know the reviewers will nitpick every missing edge case. You add authentication, rate limiting, a Dockerfile, a CI pipeline, and a README that reads like a PhD thesis. You do this for free, on your own time, while still working a full-time job or interviewing elsewhere. Your weekend? Gone. Your partner? Annoyed. Your cat? Wondering why you haven’t moved from the desk in eight hours.

And for what? The company often doesn’t even give feedback. They ghost you after you’ve poured a weekend into their little puzzle box. Or worse, they reject you because you didn’t use the exact library they happen to like internally—a library you couldn’t possibly know about because you don’t work there yet. Take-home projects aren’t inherently evil. But when they’re unscoped, unpaid, and unacknowledged, they become just another filter for privilege: people who have abundant free time, no caregiving responsibilities, and the emotional stamina to keep jumping through hoops. Everyone else gets filtered out, not because they can’t do the job, but because they have a life outside of proving themselves to strangers.

The Trivia Gauntlet: “What’s the Second Parameter of This Obscure Function?”

Some companies love trivia. They’ll ask you about the inner workings of a JavaScript engine, the exact time complexity of a rarely-used sorting algorithm, or the name of a design pattern that only exists in a 1994 Gang of Four footnote. These questions don’t test your ability to build software. They test your ability to memorize documentation. It’s a pub quiz for people who’ve mistaken recall for intelligence.

I once sat through an interview where the panel spent twenty minutes drilling me on the difference between Array.prototype.slice and Array.prototype.splice. I knew the answer, but I also knew that in any real coding session, I’d just look it up in five seconds. The interviewer nodded solemnly, as if this proved I was worthy. It proved nothing except that we were both wasting our time. Engineering isn’t a closed-book exam. It’s an open-world problem-solving discipline. The best engineers I’ve worked with are the ones who know how to find answers, not the ones who’ve preloaded every possible answer into their skulls. Memory is cheap. Judgment is expensive. Guess which one actually matters when the build is on fire at 2 a.m.

Close-up of a person typing on a laptop keyboard

Culture Fit: The Euphemism That Eats Itself

“Culture fit” is the most dangerous phrase in hiring. It sounds warm and fuzzy, like you’re looking for someone who won’t ruin the vibe. In practice, it’s a weaponized ambiguity that lets interviewers reject candidates for reasons they can’t articulate—or won’t admit. Too quiet? Not a culture fit. Too direct? Not a culture fit. Didn’t laugh at the team’s inside joke about tabs versus spaces? Definitely not a culture fit. It’s a gut check dressed up as a value system, and guts are notoriously biased.

What we should be screening for is culture contribution. Will this person make our engineering culture better? Will they challenge our bad habits, bring a new perspective, or spot the bugs in our thinking? That’s a much harder question to answer than “do I want to grab a beer with them,” which is what culture fit often boils down to. Homogeneous teams feel comfortable. They also build mediocre products. Comfort is the enemy of good engineering. You want someone who’ll say “this architecture is a disaster” in their first sprint review, not someone who’ll nod along because they’re just happy to be invited to the party.

The LeetCode Industrial Complex

Let’s talk about the elephant in the room. LeetCode, HackerRank, Codility—these platforms have become the de facto gatekeepers of software engineering jobs. They’re not assessment tools; they’re a parallel economy. Candidates spend months grinding problems that have no relationship to the work they’ll do. Companies buy enterprise subscriptions to filter candidates through a gauntlet of dynamic programming puzzles. Everyone pretends this is normal. It’s not normal. It’s a mass delusion with a SaaS billing model.

I’ve seen brilliant systems engineers fail these tests because they haven’t memorized the trick to solving “Trapping Rain Water II” in O(n) time. I’ve also seen candidates who can reverse a linked list in their sleep but can’t write a coherent commit message or design a database schema. The signal-to-noise ratio is abysmal. What’s worse, these platforms have created a shadow curriculum. Instead of learning how to build real things, aspiring developers spend months optimizing for a metric that has no correlation with job performance. It’s like training for a marathon by only doing bicep curls. You’ll look great in a tank top, but you’re not going to finish the race.

What We Should Be Testing Instead

If you want to hire someone who can do the job, test them on the job. It’s not a radical idea. Give them a realistic, time-boxed task that mirrors what they’ll actually do. Pair them with a future teammate. Watch how they navigate ambiguity, ask questions, and debug when things go wrong. Those are the skills that matter. Not whether they can recite the time complexity of quicksort from memory. Not whether they know the second parameter of some function nobody uses. Can they ship? Can they think? Can they make the codebase better than they found it? That’s the whole ballgame.

Here’s a wild concept: pay them for their time. If your interview process requires more than a few hours of work, cut a check. It signals respect, filters for serious candidates, and removes the ethical stench of asking people to work for free. You’re not a charity. They’re not volunteers. If you can’t afford to pay candidates for a trial project, you can’t afford to hire well. Simple as that.

Also, stop optimizing for false negatives. The industry’s obsession with avoiding a bad hire has created processes that reject perfectly good engineers. A bad hire is expensive, yes. But a hiring process that filters out great candidates because they didn’t memorize a textbook is a slow-motion disaster. You’re not building a team of the best; you’re building a team of the best test-takers. And test-takers are great at passing tests. Shipping software? Not so much.

Team collaborating around a table with laptops and notes

The Interviewer’s Ego Trip

Let’s be honest: a lot of bad interviews happen because the interviewer wants to feel smart. They ask esoteric questions not to assess the candidate, but to remind themselves (and the room) that they know something obscure. It’s a power move disguised as due diligence. I’ve seen interviewers ask about the internals of a framework that the company doesn’t even use, just because the interviewer read a blog post about it last week. The candidate stumbles, the interviewer nods knowingly, and another qualified person gets shown the door. This isn’t hiring. It’s intellectual bullying with a corporate expense account.

Good interviewers check their ego at the door. They’re not there to prove they’re smarter than the candidate. They’re there to discover what the candidate can do, how they think, and whether they’d make the team stronger. That requires humility, not a pop quiz. The best interview I ever conducted was one where I learned something from the candidate. That’s the sign you’re doing it right—when the conversation goes both ways, and you walk out thinking “huh, I never considered that approach.”

Processes That Scale Exclusion, Not Inclusion

Here’s the uncomfortable part: these broken processes don’t just annoy candidates. They systematically exclude people who don’t fit a narrow mold. If your hiring pipeline is optimized for young, neurotypical, native-English-speaking graduates of top-tier CS programs who can afford to spend months grinding LeetCode, congratulations—you’ve built a monoculture. You’ve also filtered out pretty much everyone else. People with families. People with disabilities. People who learned to code on the job instead of in a lecture hall. People who’d bring exactly the kind of perspective your team is missing.

Diversity in engineering isn’t about checking boxes. It’s about having people on your team who see different failure modes, who question assumptions others take for granted, who’ve solved problems in different contexts. When your hiring process filters for a single archetype, you lose all of that. You also lose people who have actual industry experience but can’t afford to take three months off to study algorithm puzzles. The irony is that many companies claim to value diversity while using hiring processes that are structurally biased against it. They’ll spend millions on recruiting initiatives, then funnel everyone through the same broken gauntlet. It’s like building a beautiful wheelchair ramp that leads to a staircase. The intent might be genuine, but the outcome is still a barrier.

What Actually Predicts Performance

Research on hiring has consistently shown that the best predictors of job performance are work-sample tests, structured interviews, and cognitive ability assessments that reflect real problem-solving—not trivia. Yet the tech industry clings to its whiteboard rituals and puzzle gauntlets like they’re sacred rites. We’ve built an entire mythology around “tough interviews” as a badge of honor. “Our interview process is really hard,” managers say, with a straight face, as if difficulty is the same thing as effectiveness. It’s not. A difficult process that measures the wrong things is just an expensive waste of time.

Work-sample tests are exactly what they sound like: give candidates a representative task, observe how they approach it, and evaluate the outcome. Pair it with a structured interview where every candidate gets the same questions, scored against the same rubric. You’ll get better signal, less bias, and candidates who feel respected—even if they don’t get the offer. Cognitive ability matters, but it’s not measured by asking someone to implement a red-black tree from memory. It’s measured by watching them reason through a novel problem with the tools they’d actually have on the job. That’s the difference between a trivia contest and an engineering assessment. One tests recall. The other tests thinking. Guess which one your production systems depend on.

The Cost of Bad Hiring Processes

Bad hiring processes don’t just hurt candidates. They hurt companies in ways that are hard to measure but impossible to ignore. When you optimize for the wrong signals, you hire the wrong people. You end up with a team that’s great at solving puzzles and terrible at shipping software. You get engineers who can ace a coding challenge but can’t collaborate, can’t communicate, and can’t handle ambiguity. They’ll crush a LeetCode hard in twenty minutes, then spend three days bikeshedding a variable name in a pull request. That’s not a win. That’s a liability with a CS degree.

You also burn out your existing team. Every hour a senior engineer spends conducting irrelevant whiteboard interviews is an hour they’re not mentoring juniors, improving architecture, or fixing technical debt. Multiply that across dozens of interviews per hire, and the cost is staggering. And then there’s the reputation cost. Candidates talk. A company known for absurd hiring practices will struggle to attract experienced engineers who have options. The best people don’t need to jump through hoops; they’ll go where they’re respected. Your hiring process is your employer brand in action. If it treats people like circus performers, don’t be surprised when the audience starts booing.

What Good Hiring Looks Like

I’ve seen it done well. A company gives you a realistic, scoped problem—something that actually happened in their codebase. You work on it for a few hours, with access to the internet, an IDE, and a real environment. Then you walk through your solution with an engineer, discussing trade-offs and alternative approaches. It feels like a collaboration, not an interrogation. You’re not performing. You’re working. And the person on the other side isn’t judging you from a throne; they’re sitting next to you, curious about how you think.

Another approach: a paid trial day or week. You work on real tasks with the team. Everyone gets to see how you operate, and you get to see if the company is somewhere you’d actually want to work. It’s honest, it’s respectful, and it produces far better signal than any whiteboard puzzle ever could. Structured interviews—where every candidate gets the same questions, scored against the same criteria—are also a massive improvement over the free-form “tell me about a time you disagreed with a coworker” style. They reduce bias and make it possible to compare candidates fairly. It’s not rocket science. It’s just treating hiring like the high-stakes decision it actually is, instead of a ritual we inherited from companies that were guessing just as much as we are.

FAQ

Why do companies still use whiteboard interviews if they’re so bad?

Because they’re easy to standardize and scale, and because they give interviewers a false sense of objectivity. Many companies also copy what big tech firms do, assuming those firms must know what they’re doing. In reality, even big tech firms are slowly moving away from pure algorithm gauntlets—but the cargo cult persists. “Google does it” is not a reason. Google also has thousands of engineers and can absorb the inefficiency. Your forty-person startup cannot. Stop copying rituals you don’t understand.

What should I do if I’m asked to invert a binary tree on a whiteboard?

You have options. You can politely ask how this task relates to the actual work you’d be doing. You can suggest an alternative assessment that better reflects real engineering. Or, if the company is inflexible, you can walk away. There are plenty of places that don’t treat hiring like a hazing ritual. Your time and dignity are worth more than a whiteboard marker. Walking away from a bad process isn’t failure—it’s self-respect. And self-respect is a pretty good filter for finding a workplace that respects you back.

How can companies fix their hiring process?

Start by defining what you’re actually hiring for. Write down the skills and behaviors that matter for the role. Then design assessments that directly measure those things. Use work-sample tests, structured interviews, and paid trial periods. Audit your process for bias regularly. And most importantly, train your interviewers to evaluate candidates on job-relevant criteria, not on how well they perform under artificial pressure. If your interviewers can’t articulate why a question predicts job performance, they shouldn’t be asking it. Period.

Isn’t it risky to skip algorithmic questions entirely?

No. Algorithmic thinking is important, but it can be assessed in context. Give candidates a real problem that requires algorithmic reasoning—something they might actually encounter on the job. Watch how they break it down, what trade-offs they consider, and how they communicate their approach. That’s far more predictive than asking them to regurgitate a textbook solution on a whiteboard. The goal isn’t to see if they’ve memorized the canonical answer. The goal is to see if they can think through something messy and come out the other side with a solution that won’t fall over in production.

Hiring is one of the highest-impact activities in any engineering organization. Getting it right means building teams that can solve hard problems, adapt to change, and create products that matter. Getting it wrong means wasting everyone’s time—and that’s the one resource none of us can afford to lose. So maybe it’s time to put down the whiteboard marker, close the LeetCode tab, and start hiring like we actually know what we’re doing.

How to Give Feedback That Changes Behavior Without Destroying Trust

Let’s get one thing straight: most engineering feedback is garbage. Not because the technical observations are wrong, but because the delivery is a masterclass in social incompetence. We’ve all seen the code review that reads like a personal indictment, or the standup comment that makes someone want to quit before lunch. The problem isn’t that we’re too harsh or too soft—it’s that we treat feedback like a bug report for a machine, not a conversation with a human who has an ego, a mortgage, and a deep-seated fear of being exposed as a fraud.

I’ve spent years in teams where the smartest people produced the dumbest interpersonal outcomes. The real technical problem in software isn’t the stack—it’s the stack of unresolved tensions, silent resentments, and passive-aggressive commit messages. Feedback is the primary tool for shaping behavior, but most engineers wield it like a blunt instrument. Here’s how to sharpen it without cutting the trust that holds a team together.

The Feedback Paradox

Here’s the ugly truth: the moment you offer feedback, you’re signaling that something is wrong. Even if you wrap it in compliments, the recipient’s brain registers a threat. Their amygdala fires up, cortisol spikes, and they’re suddenly in fight-or-flight mode. You’re not talking to a rational colleague anymore; you’re talking to a defensive primate who’s deciding whether to argue, withdraw, or sabotage you in the next sprint planning.

So the goal isn’t to make feedback painless—that’s impossible. The goal is to make the pain productive, like a vaccine that stings but prevents a worse disease. Trust isn’t built by avoiding hard conversations; it’s built by having them in a way that proves you’re on the same side. When you screw this up, you don’t just fail to change behavior—you create a team where people hide mistakes, avoid collaboration, and treat every code review like a hostage negotiation.

Two people having a serious conversation at a desk with laptops

Why Most Engineering Feedback Fails

Before we fix it, let’s autopsy the common failures. I’ve catalogued these over a decade of watching brilliant people make each other miserable.

The Drive-By Critique

This is the feedback equivalent of a hit-and-run. You drop a comment like “This architecture is over-engineered” in a pull request and disappear. No context, no alternatives, no acknowledgment of the constraints the developer was under. The recipient is left to interpret it as “You’re an idiot who wastes time.” Even if your observation is technically correct, you’ve just poisoned the well. Next time, they’ll either ignore you or spend three days writing a defensive essay in the PR comments.

The Feedback Sandwich (and Why It’s Moldy)

You know the recipe: compliment, criticism, compliment. “I love the variable naming! But the algorithm is fundamentally broken. Great indentation though!” This technique is taught in management 101 courses and it’s transparently manipulative. Engineers, who are trained to detect patterns, see it coming from a mile away. The compliments feel fake because they are fake—they’re just padding to soften the blow. The recipient now distrusts not only the criticism but also any future praise from you.

The Vague Suggestion

“Maybe we could make this more efficient.” What does that mean? More memory-efficient? Faster at runtime? Easier to read? Without specificity, feedback is just anxiety-inducing noise. The recipient is left to guess what you actually want, and they’ll probably guess wrong. Then you’ll be frustrated that they didn’t fix it, and they’ll be frustrated that you’re never satisfied. It’s a cycle of mutual disappointment.

The Public Shaming

Calling out a mistake in a team meeting or a public Slack channel isn’t feedback—it’s a power move. Even if you didn’t intend it that way, the recipient experiences it as humiliation. The lesson they learn isn’t “I should avoid that mistake”; it’s “I should avoid this person.” Trust evaporates instantly, and you’ve just created an enemy who will undermine you when you’re not looking.

The Trust-First Framework

Before you can change behavior, you need a foundation of trust. This isn’t fluffy HR nonsense—it’s a technical requirement for effective communication. If someone doesn’t trust your intentions, they’ll filter every word through suspicion. Your feedback becomes noise, not signal.

Trust in an engineering context means the recipient believes three things:

  1. You understand the problem they were trying to solve. You’ve taken the time to grasp the constraints, the trade-offs, and the context. You’re not just parachuting in with an opinion.
  2. You want them to succeed. Your feedback is aimed at making their work better, not at proving you’re smarter.
  3. You’ll have their back when things go wrong. If they take your advice and it backfires, you won’t distance yourself and say “Well, they should have known better.”

If any of these are missing, your feedback will be met with resistance. So before you open your mouth, do a quick audit: have you demonstrated these three things in your recent interactions? If not, fix that first. Trust is earned in the moments between feedback, not during the feedback itself.

Two colleagues reviewing documents together in a modern office

The Specificity Principle

Vague feedback is a trust killer. Specific feedback is a trust builder, even when it’s negative. Why? Because specificity proves you’ve engaged deeply with the work. It shows respect for the effort that went into it.

Compare these two statements:

  • “This endpoint is slow.”
  • “I profiled the /users endpoint and it’s taking 800ms under moderate load. The bottleneck seems to be the nested queries in the getUserPreferences function. We could probably get it under 200ms by eager-loading the preferences and adding a composite index on user_id and preference_type. Want me to pair on this?”

The first statement is a complaint. The second is a collaboration. It includes data, a diagnosis, a proposed solution, and an offer of help. Even if the diagnosis is wrong, the recipient can engage with it concretely. They can say “Actually, the bottleneck is the third-party API call, not the queries.” Now you’re having a productive technical discussion instead of a defensive argument.

Specificity also applies to positive feedback. “Good job on the release” is worthless. “The way you handled the database migration with zero downtime was impressive—the rollback plan and the feature flagging meant we could deploy without stress” is feedback that reinforces the exact behavior you want to see more of.

Timing: The Forgotten Variable

In engineering, we obsess over latency in our systems but ignore it in our communication. Feedback given too late is useless; the context has evaporated and the recipient can’t connect it to their actions. Feedback given too early—before you have all the data—is reckless and erodes trust when you have to walk it back.

The sweet spot is soon enough that the details are fresh, but late enough that you’ve had time to think. For a code review, that means within a day of the PR being opened, not three sprints later during a retrospective. For behavioral feedback, it means within a week of the incident, not during their annual review when they’ve forgotten it ever happened.

There’s also a circadian rhythm to feedback. Don’t ambush someone with heavy criticism at 4:55 PM on a Friday. They’ll stew all weekend and come back Monday with a resignation letter drafted. Aim for mid-morning, when cognitive resources are high and there’s time to discuss and decompress.

The Ownership Inversion

Here’s a counterintuitive move: when giving feedback, frame the problem as partly your own. This isn’t about taking blame for things that aren’t your fault—it’s about acknowledging that in a complex system, failures are rarely solo performances.

Instead of “Your code caused the outage,” try “We had an outage because of this code, and I should have caught it in review.” Or “I didn’t make the requirements clear enough, so the implementation went in a different direction than I expected.” This does two things: it lowers the recipient’s defenses, and it models the kind of accountability you want to see in the team. When people see you owning your part, they’re more likely to own theirs.

This isn’t about being nice—it’s about being accurate. In any non-trivial system, failures are multi-causal. Pretending otherwise is just bad root-cause analysis.

Behavior vs. Identity

This is the single most important distinction in feedback, and most engineers get it wrong. You’re not criticizing a person; you’re criticizing an action. But if your language doesn’t make that clear, the recipient will hear an attack on their identity.

“You’re careless” is an identity attack. “This function doesn’t handle null inputs, which caused the crash” is a behavior observation. The first triggers shame and defensiveness. The second triggers problem-solving. Always anchor your feedback to specific, observable actions and their concrete consequences. Never use adjectives that describe the person’s character.

This is especially important when giving feedback to junior engineers, who are already insecure about their competence. But it applies to seniors too—nobody’s ego is bulletproof. The moment you make it personal, you’ve lost the ability to change behavior. They’ll either fight you or shut down, and neither outcome improves the codebase.

Person writing on a whiteboard with diagrams and notes

The Feedback Protocol: A Practical Script

I’m not a fan of rigid scripts, but having a mental template prevents you from defaulting to bad habits under pressure. Here’s a four-step protocol that works in code reviews, one-on-ones, and post-mortems.

Step 1: Contextualize

Start by stating the shared goal or acknowledging the constraints. “I know we were under time pressure to ship this feature, and you made it work.” This immediately signals that you’re not ignoring the reality of the situation.

Step 2: State the Specific Observation

Describe what you saw, not what you inferred. “The payment processing module doesn’t retry on transient failures, so a brief network blip causes a hard error for the user.” Stick to facts, not interpretations.

Step 3: Explain the Impact

Connect the behavior to a concrete outcome. “This means that during yesterday’s outage, 40 transactions failed permanently instead of being queued for retry. We lost revenue and got support tickets.” Impact makes the feedback matter; without it, you’re just nitpicking.

Step 4: Collaborate on a Solution

End with a question or an offer, not a demand. “How do you think we should handle this? I was considering a retry queue with exponential backoff, but I’d like your input.” This turns the feedback into a joint problem-solving session. The recipient leaves feeling empowered, not scolded.

Receiving Feedback: The Other Half of Trust

Giving feedback well is only half the equation. How you receive feedback determines whether people will keep giving it to you. If you get defensive, argue every point, or retaliate later, you’re training your team to avoid you. They’ll let your mistakes slide until they become catastrophes.

When someone gives you feedback, your first job is to listen without interrupting. Your second job is to thank them—even if the delivery was clumsy, even if you disagree. “Thanks for bringing this up. Let me think about it and get back to you” is a perfectly valid response. It buys you time to process without reacting emotionally.

If the feedback is vague, ask clarifying questions. “When you say the code is hard to follow, can you point to a specific function?” This isn’t defensive—it’s turning vague criticism into actionable information. If the feedback is wrong, you can explain your reasoning later, after you’ve demonstrated that you took it seriously.

Feedback in Code Reviews: The Highest-Stakes Arena

Code reviews are where engineering feedback happens most frequently and where trust is most often destroyed. The asynchronous, text-only medium strips away tone and context, leaving every comment open to the worst possible interpretation. A simple “Why did you do this?” can read as “What were you thinking, you moron?”

Here are specific rules for code review feedback:

  • Use questions, not judgments. “What’s the reasoning behind this approach?” instead of “This is wrong.” Questions invite explanation; judgments invite defensiveness.
  • Distinguish between blocking and non-blocking feedback. Use labels like “nit:” for style preferences and “blocking:” for functional issues. This prevents the recipient from treating every comment as a crisis.
  • Offer to pair. If the feedback is complex, say “I think we could simplify this—want to jump on a call and pair on it?” This moves the conversation from asynchronous sniping to collaborative problem-solving.
  • Don’t review code when you’re angry. If you just spent an hour debugging something caused by this PR, step away before you comment. Anger leaks into your wording and escalates the situation.

When Feedback Goes Wrong: Repairing Trust

Even with good intentions, you’ll sometimes screw up. You’ll phrase something poorly, or the recipient will have a bad day and take it harder than you intended. When that happens, don’t double down—repair.

Acknowledge the impact, not just the intent. “I can see that my comment came across as harsh, and I’m sorry. That wasn’t my intention. Let me try again.” This validates their experience without making you a villain. Then restate your feedback using the protocol above.

If you’re the one who received poorly-delivered feedback, give the other person a chance to repair before you escalate. “I’m sure you didn’t mean it this way, but that comment felt like a personal attack. Can we rewind?” Most engineers will appreciate the directness and adjust.

FAQ

What if someone consistently ignores my feedback?

First, check your delivery. Are you being specific? Are you explaining the impact? Are you offering collaboration? If you’re doing all that and they still ignore you, the problem isn’t feedback—it’s a performance issue. Escalate to their manager with concrete examples of the feedback you’ve given and the behavior that hasn’t changed. But don’t use escalation as a threat during feedback; that destroys trust instantly.

How do I give feedback to someone more senior than me?

Frame it as an observation from your perspective, not a judgment from a position of authority (which you don’t have). “I noticed that when we cut scope on the project, the team was confused about priorities. From my perspective, clearer communication about the trade-offs would have helped.” Senior people are often blind to their own impact because nobody tells them. If you’re respectful and specific, most will appreciate it. If they don’t, that’s a red flag about the culture.

Is it ever okay to give feedback publicly?

Rarely. Positive feedback can be public—calling out someone’s great work in a team meeting builds trust and reinforces behavior. But negative feedback should almost always be private. The exception is when the behavior affects the whole team and needs immediate correction, like someone violating a safety protocol. Even then, focus on the behavior, not the person: “We need to make sure all database migrations go through the review process” rather than “Alice pushed a migration without review.”

How do I handle feedback about my own code that I disagree with?

First, assume good intent. The reviewer probably isn’t trying to undermine you. Second, ask for clarification: “Can you help me understand the concern? I chose this approach because of X constraint.” Third, if you still disagree, propose a compromise or escalate to a technical lead for a tiebreaker. Never just ignore the feedback—that signals you’re not a team player. And never argue in the PR comments for three days; that’s what calls are for.

The Long Game

Feedback isn’t a one-off transaction; it’s a continuous investment in your team’s capability and cohesion. Every interaction either deposits into or withdraws from the trust account. When the balance is high, you can give tough feedback and it’ll be received as help. When the balance is low, even mild suggestions will be seen as attacks.

Build that balance deliberately. Give specific, public praise when you see good work. Admit your own mistakes openly. Ask for feedback on your own code and receive it gracefully. When people see you modeling the behavior you’re asking for, they’ll follow. Not because you told them to, but because you showed them it’s safe.

The best engineering teams aren’t the ones with the smartest individuals—they’re the ones where feedback flows freely, trust is high, and everyone is focused on improving the system rather than protecting their ego. That’s not a cultural accident; it’s a technical achievement. Treat it like one.

How to Give Feedback That Actually Changes Behavior Without Nuking Trust

Look, most engineering feedback lands about as well as a code review that just says “LGTM” while the architecture is held together with hope and a sticky note. We’ve all been there. You sit down with someone, try to tell them something they need to hear, and suddenly you’re the villain in a performance review drama. Or worse, you’re the person who said nothing, and now the same broken pattern has shipped to production for the sixth time.

Here’s the thing nobody wants to admit at standup: the way we talk to each other about work is a technical problem. Not a soft-skills seminar. Not a “let’s hold hands and share feelings” exercise. I’m talking about the actual systems, protocols, and failure modes of human communication inside an engineering culture. And most of you are running legacy code in your brain when it comes to giving someone a piece of critical input.

This isn’t about being nice. It’s about being surgically precise. I’ve seen teams where the “blunt” engineer leaves a trail of resentment so wide you could drive a sprint retrospective through it. I’ve also seen teams where everyone is so terrified of conflict that bugs get renamed “known behaviors” and shipped with a shrug. Both are trust-failures. Both cost you velocity, quality, and the ability to look your colleagues in the eye.

So let’s fix the damn protocol.

Two engineers discussing code on a monitor

The Feedback OS Is Corrupted

Most people treat feedback like a ticket they file against another human. They wait until the bug is reproducible, document the expected vs. actual behavior, and then assign it a priority level that only exists in their own head. The recipient opens this ticket and immediately goes into defensive triage mode. “Cannot reproduce.” “Working as intended.” “Won’t do.”

This model is broken because humans are not Jira. We don’t process emotional payloads through a REST API. When you frame feedback as a defect report, you’re triggering every insecurity circuit that person has. Their brain starts scanning for evidence that you’re wrong, that you’re biased, that you don’t have the full context. And the actual behavior change you wanted? Buried under a pile of mental stack traces.

The real problem is that feedback is often delivered without any shared understanding of what “good” looks like. It’s like telling a junior dev their code is “not clean” without ever defining your team’s architecture principles. You’re expecting them to read your mind, and then you’re surprised when they get defensive. That’s not a communication failure on their part. That’s you shipping an undocumented API and getting mad when the client sends a malformed request.

Define the Schema Before You Send the Payload

Before you ever open your mouth to give someone feedback, you need to ask yourself one question: what is the specific, observable behavior I want to change, and what is the observable behavior I want to see instead? If you can’t articulate that in a way a robot could validate, you’re not ready to talk to a human.

“You need to be more proactive” is garbage feedback. It’s a vague judgment wearing the skin of helpfulness. “In the last three sprint plannings, you didn’t raise any concerns about the technical scope, and we ended up with unplanned work that delayed the release” is actual data. That’s something a person can look at and think, “Okay, I can change that.”

This is not about being pedantic. It’s about giving the other person a spec they can implement. Engineers are builders. We understand inputs, outputs, and acceptance criteria. When you give feedback that looks like a poorly written user story, you’re insulting their professional intelligence. When you give feedback that looks like a clear bug report with reproduction steps, you’re showing respect for their ability to fix things.

Team collaborating around a whiteboard with diagrams

The Intent-Impact Gap

Here’s where a lot of well-meaning engineers screw up. They assume that because they didn’t intend to cause harm, the other person shouldn’t feel harmed. That’s like saying because you didn’t intend to introduce a race condition, the production outage shouldn’t count. The impact is what the system experienced, not what you meant to deploy.

When you give feedback, you have to acknowledge this gap explicitly. Not with some performative “I’m sorry you feel that way” nonsense. I mean actually saying: “I know you were trying to move fast and unblock the team, and I respect that intent. The impact, though, was that we lost two days debugging because the commit messages didn’t explain the context. Can we figure out a way to keep the speed without losing the traceability?”

That sentence does more psychological heavy lifting than a month of “communication training.” It separates the person’s identity from the behavior. It validates their intentions while being unflinching about the consequences. And it positions the two of you as collaborators solving a shared problem, not as judge and defendant.

Trust Is a Cache That Invalidates Easily

Engineering teams run on trust. It’s the cached credential that lets you merge code without every line being scrutinized by a committee. But trust is a distributed cache with terrible invalidation logic. One bad interaction can poison the entire system, and rebuilding it takes exponentially longer than tearing it down.

The fastest way to corrupt the trust cache is to give feedback that attacks identity instead of behavior. “You’re disorganized” is an identity attack. “Your project board hasn’t been updated in two weeks, and it’s making dependency tracking harder for the team” is behavioral feedback. The first one makes someone want to prove you wrong. The second one makes someone want to update their project board.

Another trust-killer: giving feedback only when things go wrong. If the only time you talk to someone about their work is to point out flaws, you’ve trained their nervous system to associate your voice with threat. That’s not feedback. That’s a conditioning experiment, and you’re the negative stimulus. Regular, specific positive feedback isn’t fluffy team-building crap. It’s building up a reserve of goodwill so that when you do need to deliver something hard, the relationship can absorb the load.

Timing Is a Performance Characteristic

Feedback delayed is feedback denied. The longer you wait after an observed behavior, the more the memory degrades, the context gets fuzzy, and the emotional charge dissipates into weird resentment. You ever had someone bring up a thing you did three months ago in a performance review? It feels like an ambush because it is an ambush. You’ve been sitting on data that could have helped the person adjust in real time, and instead you saved it as ammunition for a formal meeting.

The sweet spot for behavioral feedback is typically within 24 to 48 hours. Long enough that you can gather your thoughts and check your own emotional state. Short enough that the event is still fresh and actionable. If you’re angry, wait until you’re not. Feedback delivered in anger is just data corruption with extra steps.

Engineer deep in thought at a desk

The Architecture of a Good Feedback Conversation

Let’s get tactical. Here’s a structure that actually works, tested across more messy team dynamics than I care to count.

1. Set the context without drama. Don’t schedule a “serious talk” with a cryptic calendar invite. That’s the professional equivalent of “we need to talk” from a partner. Just say: “Hey, I wanted to chat about something I noticed in the last sprint. Got 15 minutes?”

2. Lead with the observation, not the conclusion. “I noticed that in the last three code reviews, your comments were focused exclusively on formatting issues. I didn’t see any feedback on the logic or architecture choices.” This is a fact. It’s not an opinion. It’s not a judgment. It’s a camera recording.

3. Describe the impact on the team or the work. “The effect is that some design decisions that could have been caught early made it into the codebase, and we’re now refactoring them under deadline pressure. I think you have the experience to catch those things, so I’m wondering what’s getting in the way.”

4. Ask a genuine question and shut up. The silence after you ask “What’s your perspective?” is the most important part of this whole protocol. You have to actually listen. Not prepare your rebuttal. Not wait for your turn to talk again. Listen. The other person might have context you’re missing. They might be burned out. They might be dealing with something outside work that’s draining their cognitive capacity. Or they might just disagree with your assessment, and that’s data too.

5. Agree on the next behavior, not the next feeling. “So going forward, can we try having you focus on one architectural comment per review, even if it’s just a question?” This is a lightweight contract. It’s testable. Next sprint, you can both look back and see if it happened.

This structure works because it respects the other person’s agency. You’re not issuing a command. You’re presenting data, describing its system-level effects, and inviting collaboration on a fix. That’s engineering. That’s debugging a process, not a person.

When the Feedback Recipient Is the System, Not the Individual

Sometimes the behavior you need to change isn’t one person’s fault. It’s a team norm that nobody has named. Everyone knows that the standups run 25 minutes and are mostly status theater. Everyone knows that the on-call rotation is a sacrificial ritual. But nobody says it out loud, because saying it out loud feels like accusing your friends.

In these cases, the feedback needs to be directed at the system, not at any single individual. “I’ve observed that our retrospectives tend to produce action items that nobody follows up on. The impact is that we keep having the same conversations each sprint. I’d like to propose that we assign a single owner to each action item and review them at the start of the next retro.”

This is still feedback. It’s still pointing at a gap between expected and actual behavior. But by framing it as a systemic issue, you avoid triggering anyone’s personal defenses, and you position yourself as someone who’s trying to improve the team, not tear down a teammate.

FAQ: Engineers Asking the Hard Questions

What if the person gets defensive no matter how carefully I phrase it?

Defensiveness is often a fear response, not a rational argument. If someone’s amygdala is running the show, no amount of logical framing will land. In that case, pause the content of the feedback and address the dynamic directly: “It seems like this is hitting a nerve, and I don’t want to push if this isn’t a good time. Can we take a break and come back to it?” That gives them a chance to regulate. If they still can’t engage, the trust cache is probably already corrupted, and you have a deeper problem that a single feedback conversation won’t fix.

How do I give feedback to someone more senior than me?

Same protocol, different power dynamic. Lead with curiosity: “I noticed X, and I wanted to understand your thinking because it seemed different from what I expected.” You’re not telling them they’re wrong. You’re seeking to understand their model. If there’s a real problem, the data will speak for itself. And if you’re wrong, you learn something. Either way, you’ve demonstrated that you’re paying attention and thinking about the system, not just your own tickets.

Can written feedback via Slack or email ever work?

Written feedback strips out tone, facial expression, and the ability to read the room in real time. It’s a high-latency, low-bandwidth channel for an interaction that requires nuance. Avoid it for anything that has emotional weight. The only exception is when you’re following up on a verbal conversation to document what was agreed. A quick “Thanks for the chat earlier. Just to confirm, we’re going to try X going forward” can be useful. But leading with text is like deploying straight to prod without a staging environment. You might get lucky, but the blast radius is huge when it fails.

What if I’m the one receiving feedback badly? How do I get better?

First, recognize that the physiological reaction—racing heart, tight chest, urge to explain—is just your body doing its thing. It’s not a signal that you’re under attack. Breathe. Remind yourself that feedback is data about how your actions are landing, not a verdict on your worth as a human. Ask clarifying questions that are actually clarifying, not disguised counterarguments: “Can you give me a specific example?” “What would success look like in that situation?” If you need time to process, say so: “I want to think about this before I respond. Can I come back to you tomorrow?” That’s not weakness. That’s professional maturity.

Giving feedback that sticks is a technical skill. It’s about designing a message that can survive the noisy, emotionally lossy channel between two human brains. It’s about respecting the person enough to give them a spec they can actually build against. And it’s about understanding that the real product you’re all shipping isn’t just code—it’s the culture that writes the code. If you treat that culture like a legacy monolith that nobody dares to refactor, you’ll get exactly the bugs you deserve.

Now go break something, fix it, and talk to your teammates like the capable adults they are.

How to Give Feedback That Actually Changes Behavior (Without Making Everyone Hate You)

Most engineering feedback is a polite waste of breath. It’s either a sugar-coated nothingburger that leaves the recipient confused, or blunt-force trauma that sends them straight to LinkedIn. The real technical problem in our culture isn’t the stack—it’s how we talk about each other’s work without leaving a crater.

I’m Fritz Muller, and I’ve spent more time debugging human systems than code. Here’s the uncomfortable truth: if your feedback doesn’t change behavior, you’re just having a chat. And if it burns trust, you’re not a leader—you’re a liability.

Two developers discussing code on a monitor

The Feedback Paradox: Why We Suck at This

Engineers are trained to spot defects. We’re excellent at finding the one misplaced semicolon in a thousand lines of code. That same brain, applied to a colleague’s pull request or presentation style, becomes a weapon. We confuse “accurate” with “helpful.” We think pointing out what’s broken is the same as fixing it.

The paradox is simple: feedback must be honest enough to matter and safe enough to hear. Most of us pick one. The passive-aggressive architect who writes “interesting approach” in a PR review has chosen safety. The senior dev who says “this is garbage” during standup has chosen honesty. Both fail. One preserves a fake peace; the other wins a battle and loses the war.

The Trust Battery Concept

Think of trust as a battery. Every interaction either charges or drains it. When the battery is low, even mild criticism feels like an attack. When it’s high, you can say almost anything. The mistake is delivering feedback without checking the charge level first. If you’ve never acknowledged someone’s good work, your first negative comment will short-circuit the relationship.

I once watched a CTO dismantle a junior engineer’s system design in a public Slack channel. Technically, every point was correct. The design had scalability holes you could drive a truck through. But the CTO had never publicly praised that engineer for anything. The trust battery was at zero. The engineer quit within a month. The feedback was accurate. It also destroyed a promising career trajectory because the delivery was calibrated for a robot, not a human.

The Behavior-Specific Feedback Loop

Vague feedback is emotional litter. “You need to be more proactive” is a feeling, not a directive. “You didn’t update the runbook after the last incident, which meant the on-call person spent two hours guessing” is a behavior. One invites defensiveness. The other invites a specific fix.

The loop I enforce on my teams is painfully simple:

  1. Observe the specific action. Not the person’s character, not their intentions—the observable thing they did or didn’t do. “You interrupted Priya three times during the design review.”
  2. Describe the impact. Not your feelings—the concrete consequence. “That meant her concerns about the database schema weren’t heard until we’d already committed to the wrong indexing strategy.”
  3. Request a change. Make it a clear, doable action. “Next time, let her finish her point before jumping in. If you disagree, jot a note and circle back.”

This isn’t soft. It’s precise. It strips out judgment and leaves only the mechanics of improvement. When I give feedback this way, there’s nothing to argue about. Either you interrupted or you didn’t. Either the schema was wrong or it wasn’t. The conversation stays on the event, not the ego.

Person writing feedback notes on a glass board

Why “Radical Candor” Gets Misused

Somewhere along the line, the concept of radical candor got hijacked by people who just wanted to be rude. They heard “challenge directly” and ignored “care personally.” The framework isn’t a license to unload. It’s a two-axis model: if you’re not investing in the relationship, your directness is just obnoxious aggression.

I’ve seen managers start feedback sessions with “I’m just being radically candid” and then deliver a monologue about someone’s shortcomings. That’s not candor. That’s a performance review disguised as courage. Real candor is a conversation. It starts with a question like “How do you think that meeting went?” and then shuts up long enough to hear the answer.

Timing and Setting: The Invisible Factors

Feedback delivered in public is punishment. I don’t care if you frame it as a “teaching moment.” If there are witnesses, the recipient’s brain flips into self-preservation mode. They’re not processing your words—they’re managing their reputation. Save it for a private channel or, better, a face-to-face conversation.

Timing is equally critical. Feedback given right after the event is gold. Feedback given three weeks later during a formal review is a betrayal. If you sat on a problem until the quarterly review, you weren’t trying to help—you were building a case. I tell my teams: if you can’t deliver feedback within 48 hours, ask yourself why you’re hoarding it.

The 24-Hour Rule for Emotional Feedback

There’s an exception. If you’re angry, wait. Hot feedback is almost always poorly framed. I’ve sent drafts of furious messages, then deleted them the next morning. The core issue was real; the wording was radioactive. Give yourself a day to separate the emotion from the observation. Then deliver the observation cold and clean.

Receiving Feedback Like a Functioning Adult

Giving feedback is half the equation. The other half is your own reaction when the mirror is turned on you. Most engineers I know have a brittle relationship with criticism. We’re used to being the smartest person in the room, and feedback threatens that identity.

My rule is brutal: when someone gives you feedback, your only job for the first two minutes is to listen and ask clarifying questions. No defending. No explaining. No “well, actually.” If you jump straight to justification, you’re telling the other person their observation isn’t valid. You’re training them to never speak up again.

Try this script: “Thanks for telling me. Can you give me an example of when I did that?” Then stop. Let the silence sit. Your brain will scream at you to argue. Ignore it. You can decide later whether the feedback is accurate. In the moment, your only task is to understand.

Team having a constructive feedback discussion

When Feedback Is Wrong

Sometimes feedback is genuinely off-base. The person misunderstood your intent, or they’re projecting their own insecurities. Even then, don’t dismiss it outright. Wrong feedback often points to a communication gap. If someone thinks you’re being dismissive, maybe you’re not explaining your reasoning clearly. The feedback about you might be inaccurate, but the feedback about their experience of you is always real. Address that experience, not the accusation.

Feedback in Code Reviews

Code reviews are the most frequent feedback channel in engineering, and we’ve normalized a toxic culture around them. Nitpicking variable names is not feedback—it’s bike-shedding. Dumping ten comments on a PR without a single positive note is not thorough—it’s demoralizing.

I enforce a simple structure: every PR comment that identifies an issue must also suggest a solution or ask a genuine question. “This is wrong” is a complaint. “This could cause a race condition because of the async call on line 34—what if we move the await up?” is collaboration. The first makes you a critic. The second makes you a colleague.

And for the love of everything, leave approval comments that are specific. “Looks good” is worthless. “The refactor on the payment module is clean—much easier to test now” tells the developer exactly what they did right. It charges the trust battery so that when you do flag a problem, it lands on fertile ground.

Separating Style from Substance

Too many code review comments are about personal preference disguised as objective truth. Unless your team has an agreed-upon style guide, your opinion on spacing versus tabs is just noise. Flag bugs, logic errors, and architectural concerns. If it’s a stylistic nit, either automate it with a linter or let it go. Your aesthetic preferences are not feedback.

Cultural Damage and Repair

Broken feedback cultures don’t fix themselves. They fester. People stop speaking up in meetings. PRs get rubber-stamped. The loudest voice wins by default. I’ve walked into teams where the official value was “blameless culture” but the reality was a silent blame-fest where mistakes were whispered about in DMs.

Repair starts with one person modeling the behavior. When a senior engineer says, “I was wrong about that approach—thanks for catching it,” they give everyone else permission to be imperfect. When a manager asks for feedback on their own decisions and then visibly acts on it, they demonstrate that feedback isn’t a trap.

If you’re in a team where feedback is broken, don’t wait for permission. Start small. Give one piece of behavior-specific, positively-framed feedback to a peer this week. Ask for feedback on something you did, and receive it without a flinch. Culture isn’t a top-down decree. It’s the sum of tiny, repeated actions.

FAQ

How do I give feedback to someone more senior than me?

Frame it as sharing your perspective, not delivering a verdict. “I noticed something in the planning meeting that I wanted to share—can I run it by you?” Seniority doesn’t mean infallibility. If the senior person reacts poorly to respectful, specific feedback, that’s a them problem, not a you problem. Document the exchange anyway.

What if I’ve already damaged trust with someone?

You can’t retroactively fix a bad delivery, but you can own it. Go to the person privately and say, “I think I handled that feedback badly. I should have been more specific/private/timely. Can I try again?” This isn’t groveling—it’s demonstrating that you care more about the relationship than being right. Trust can be rebuilt, but only if you’re willing to admit the initial failure.

How do I know if my feedback actually changed behavior?

Watch, don’t ask. After delivering feedback, note whether the specific action shifts within the next two weeks. If you said “please update the runbook after incidents” and the next incident still has no runbook update, your feedback didn’t land. Follow up: “Hey, I noticed the runbook wasn’t updated after last night’s outage. What got in the way?” This turns a missed expectation into a joint problem-solving session, not a second scolding.

Can written feedback ever be as effective as spoken?

Written feedback is permanent and prone to tone misinterpretation. A comment like “rethink this” in a PR can read as curt dismissal when you meant it as collaborative brainstorming. For anything with emotional weight, deliver it verbally—or at least start there. Use text for documenting agreements, not for initiating difficult conversations. If you must write, read it aloud before sending. If it sounds cold, it will read colder.

The engineering culture problem isn’t a mystery. We’ve just convinced ourselves that technical skills excuse human clumsiness. They don’t. Feedback is a skill, not a personality trait. You can learn it, practice it, and measure it by whether the people around you actually change what they do. If they don’t, your feedback method is broken—and that’s the real bug you need to fix.

Why Your Architecture Decisions Are Only as Good as the Documentation Around Them

I’ve watched more systems die from lousy documentation than from lousy code. That’s not a metaphor. That’s a body count. A perfectly decent architecture—one that could have scaled, could have been maintained, could have made the company actual money—gets gutted because nobody wrote down why it was built that way. Six months later, a new hire with a messiah complex rewrites the whole thing in a weekend hackathon, and suddenly your pager is screaming at 3 a.m.

Here’s the ugly truth: an architecture decision without a written record is just a rumor. It spreads, mutates, and eventually becomes the thing everyone curses at but nobody understands. If you’re not documenting your architectural choices, you’re not engineering. You’re just decorating a house of cards.

The Half-Life of an Undocumented Decision

Let’s talk about decay. Not bit rot—decision rot. You make a call in a meeting: “We’re going with a modular monolith instead of microservices because our team is five people and our latency budget is tighter than a hipster’s jeans.” Everyone nods. Two people leave. Three new people join. The original Slack thread scrolls off into the void. Now that decision exists only as a vague tribal memory, and the new folks are already drafting a proposal to “fix” the monolith by splitting it into 47 nanoservices.

This isn’t a people problem. It’s a culture problem wearing a technical mask. The engineering culture that treats documentation as an afterthought is the same culture that will burn three sprints rewriting a service that was built in three days, all because nobody understood the original constraints. You’re not saving time by skipping the write-up. You’re borrowing time at loan-shark interest rates.

Frustrated developer staring at messy whiteboard diagrams

Documentation Is Not a Novel

Let’s kill a sacred cow right now: nobody wants to read your 40-page architecture manifesto. That’s not documentation. That’s a cry for help. Good architecture documentation is a decision log, not a dissertation. It answers five questions and then gets out of the way:

  • What did we decide?
  • Why did we decide it? (Context, constraints, trade-offs)
  • What alternatives did we reject and why?
  • When did we decide it? (Date, people in the room)
  • What are the known consequences or risks?

That’s it. If you can’t fit it on a single page, you’re not documenting a decision. You’re writing a memoir. Stop it.

I once walked into a codebase where the “architecture doc” was a 60-page Google Doc with 147 unresolved comments. The team had been arguing about it for eight months. The system itself had been in production for two years. The doc was a fossilized argument, not a guide. Nobody read it. Everyone just asked Dave. Then Dave quit. Then everyone panicked.

The Real Cost of Missing Context

When a new developer opens a pull request that casually proposes replacing your hand-rolled caching layer with Redis, they’re not being stupid. They’re operating with the information they have. They see a custom solution and think “legacy cruft.” They don’t know that you tried Redis three years ago and it fell over under peak load because of a kernel bug that only triggered with your specific access pattern. They don’t know that the hand-rolled layer has 18 months of tuning for your exact workload. They don’t know because nobody wrote it down.

So you reject the PR. Maybe you leave a terse comment. The new developer feels dismissed. They start to believe the codebase is run by grumpy wizards who hate progress. Trust erodes. Six months later, they leave for a company that “embraces modern tools.” You lost a good engineer because you couldn’t be bothered to explain your past decisions. That’s not a retention problem. That’s a documentation problem wearing a hoodie.

Developer confused by undocumented code on multiple screens

Architecture Decision Records: The Antidote to Amnesia

If you’re not using Architecture Decision Records (ADRs), you’re doing oral history. And oral history is a terrible way to run a software project. ADRs are short, plain-text files stored in your repository, right next to the code they influence. They’re not wiki pages that rot in a separate system. They’re not Confluence documents that require a VPN, two-factor auth, and a blood sacrifice to access. They’re right there, in version control, evolving with the code.

An ADR has a title, a status (proposed, accepted, deprecated, superseded), a context section, a decision section, and a consequences section. That’s it. You write one when you make a significant architectural choice. You link to it from your code. When someone proposes a change that contradicts an existing ADR, they either write a new ADR that supersedes the old one or they have a very awkward conversation in the pull request comments.

This isn’t bureaucracy. This is engineering hygiene. You wouldn’t deploy code without tests. You shouldn’t deploy architecture without a record of why it exists.

What Qualifies as an Architecture Decision?

Not every choice needs an ADR. Choosing between tabs and spaces is a style guide issue, not an architecture decision. But if you’re picking a database, a messaging pattern, a deployment topology, or a significant library that shapes how the system behaves—write it down. If the decision affects more than one team, write it down. If the decision has a cost to reverse, write it down. If you’re choosing something unusual or counterintuitive, definitely write it down.

Here’s a rule of thumb: if you’d be annoyed explaining this decision for the third time to a new team member, it belongs in an ADR.

When Documentation Becomes a Weapon

I’ve seen teams use documentation as a political tool. They write overly detailed specs not to inform, but to constrain. They create processes that require sign-off from three architects and a security review before anyone can change a CSS file. That’s not documentation. That’s a power play with extra steps.

Good documentation empowers. Bad documentation controls. If your architecture docs are being used to say “no” more often than they’re used to say “here’s why we did this, now make it better,” you’ve built a bureaucracy, not a knowledge base. Burn it down.

I once consulted for a company where the “architecture review board” was just two senior engineers who hadn’t written production code in four years. They required a 20-page document for any new service. Teams started building shadow services to avoid the process. The official architecture was a fiction. The real architecture was whatever people could sneak past the gatekeepers. That’s what happens when documentation becomes a weapon.

Messy server room with tangled cables symbolizing undocumented complexity

Write for the Person Who Will Replace You

Here’s a mental exercise: imagine you win the lottery tomorrow and vanish. Who picks up your code? What do they need to know to not immediately hate you? Write for that person. Write with the assumption that the reader is smart, motivated, and completely ignorant of every conversation you’ve had for the last two years.

This means explaining why, not just what. A comment that says “// increment counter” is useless. A comment that says “// increment counter before the check to avoid a race condition with the cleanup job (see ADR-004)” is gold. The first is noise. The second is context. Context is what separates a codebase you can maintain from a codebase you flee.

And for the love of everything, date your decisions. Nothing is more infuriating than finding a document that says “We decided to use MySQL because it’s the best option available” with no date, no alternatives listed, and no mention of who “we” is. That document is worse than useless. It’s misleading. It implies a permanence that doesn’t exist in software.

The Half-Life of a Decision

Every architecture decision has an expiration date. It might be six months. It might be six years. But eventually, the context that made it right will change. Your monolith was the right call when you had three engineers and one product. Now you have forty engineers and seven products. The decision hasn’t aged well. That’s fine. That’s expected. What’s not fine is pretending the original decision is still valid without re-evaluating it.

Good documentation makes this re-evaluation possible. When you have a record of the original context, you can compare it to the current context and make a deliberate choice: keep the decision, modify it, or replace it. Without that record, you’re just guessing. You’re making decisions based on folklore and frustration.

I’ve seen teams spend months “modernizing” a system only to discover they’d recreated the exact problems the original architecture was designed to avoid. The original team had solved those problems through painful experience. But because nobody wrote it down, the new team had to learn the same lessons the hard way. That’s not iteration. That’s amnesia.

Documentation as a Hiring and Onboarding Tool

When a senior engineer interviews with your company, they’re not just evaluating your tech stack. They’re evaluating your engineering culture. And one of the fastest ways to signal that your culture is a mess is to have no coherent architecture documentation. It tells candidates: “We make decisions by vibe. We forget why we did things. You’ll spend your first six months reverse-engineering tribal knowledge from git blame and Slack logs.”

Good candidates have options. They’ll choose the company where they can read a few ADRs and understand the system’s evolution. They’ll choose the company where the architecture isn’t a secret society.

Onboarding is the same story. A new engineer with good documentation can be productive in days. Without it, they’re in a fog for months. That fog costs real money. It costs missed deadlines, bad decisions, and rework. If you’re not factoring documentation into your onboarding costs, your spreadsheets are lying to you.

When the Code Is the Documentation (and Why That’s a Lie)

There’s a certain breed of developer who says “the code is the documentation.” These people are either lying or have never maintained a system they didn’t write. Code tells you what and how. It does not tell you why. It does not tell you what was considered and rejected. It does not tell you about the meeting where three senior engineers screamed at each other for two hours before arriving at a compromise that looks simple in code but was born from blood and fire.

Code is a snapshot of the final state. It’s the last page of a novel. Architecture documentation is the plot summary. Without it, you’re trying to understand the story by reading the last page over and over.

What Happens When Documentation Is Actually Good

I’ve seen teams where architecture documentation is a first-class citizen. ADRs are in the repo. They’re linked from the code. They’re updated when decisions change. The result? Onboarding takes days, not months. Refactoring is informed, not reckless. Arguments about “why we did this” end with a link to a document, not a shouting match in Slack.

These teams aren’t staffed by superhumans. They’re staffed by engineers who understand that writing down why you did something is part of doing it. They treat documentation like tests: not optional, not an afterthought, but a core part of the deliverable.

And here’s the kicker: these teams move faster. They make better decisions. They have fewer incidents. Because they’re not constantly rediscovering their own history.

FAQ

How detailed should an architecture decision record be?

Short enough to read in five minutes, long enough to capture the context, decision, alternatives, and consequences. If you need diagrams, link to them. Don’t embed a novel. The goal is clarity, not completeness. A decision record that nobody reads is just as useless as no record at all.

What if we made a bad decision? Should we still document it?

Absolutely. In fact, bad decisions are the most important ones to document. Write down what you decided, why you thought it was right at the time, and what actually went wrong. That’s not a failure—it’s a vaccine. Future engineers will see it and avoid repeating the same mistake. If you bury it, you’re guaranteeing someone will make it again.

How do we convince management to invest time in architecture documentation?

Stop framing it as “documentation.” Frame it as “reducing onboarding time, preventing bad rewrites, and avoiding production incidents.” Then show them the math. A single avoided incident can save more engineering hours than a year of writing ADRs. If they still don’t get it, ask them how much they’d pay to have a record of every major decision made in the last two years. That’s what you’re offering to build going forward.

What’s the difference between architecture documentation and code comments?

Code comments explain the how and sometimes the why of a specific line or function. Architecture documentation explains the why of the system’s structure, the trade-offs, and the constraints that shaped it. Code comments are local. Architecture documentation is global. You need both, but they serve different purposes.

Stop treating architecture decisions like campfire stories. Write them down. Your future self—and every engineer who inherits your code—will thank you. Or at least they won’t curse your name in the middle of an outage. That’s the real win.

Your Feedback Is Broken. Here’s the Fix.

Let’s not pretend. Most engineering feedback is either a sugar-coated nothingburger that leaves the recipient confused, or a blunt-force trauma session that sends them straight to LinkedIn’s “Open to Work” feature. The real technical problem in this industry isn’t Kubernetes scaling or microservice latency—it’s that we’re collectively terrible at telling each other when we’re screwing up. I’ve watched brilliant teams implode not because of bad code, but because of bad conversations. So here’s my unfiltered take on how to give feedback that actually changes behavior, without making people hate you—or themselves.

Two developers talking seriously at a desk with laptops

The Feedback Paradox: Why We’re So Bad at This

Here’s an uncomfortable observation: most engineers would rather refactor a 10,000-line legacy monolith than give a teammate honest feedback. We’re trained to optimize systems, not relationships. So when someone’s behavior is the bug, we either ignore it until the whole team crashes, or we deploy a patch so aggressive it breaks everything else. Trust evaporates. Resentment festers. The person either doesn’t change, or changes in all the wrong ways—getting defensive, withdrawn, or passive-aggressive.

The root cause is embarrassingly simple: we treat feedback as a judgment instead of a tool. A judgment says “you are bad.” A tool says “here’s a lever that might work better.” That distinction isn’t just semantic—it’s the entire game. Frame feedback as a tool, and you’re collaborating on a problem. Frame it as a judgment, and you’re just being an asshole with extra steps.

Step One: Diagnose Before You Prescribe

Picture a junior dev who pushes a commit that breaks the build. The lazy feedback is “Don’t break the build, idiot.” The slightly-better-but-still-lazy version is “Please run tests locally before pushing.” Both miss the point entirely. Why did they skip the tests? Were they rushed? Did they not know how to run them? Is the test suite so glacially slow that everyone bypasses it and they just got unlucky today? If you don’t understand the system that produced the behavior, your feedback is just noise.

Before you open your mouth, do five minutes of debugging. Ask yourself: What’s the actual gap? Is it knowledge, motivation, environment, or clarity? If the person doesn’t know the expectation, that’s a clarity problem—and it’s probably your fault for not documenting it. If they know but lack the skill, that’s a knowledge gap—and screaming won’t magically upload information into their brain. If they have the skill but don’t do it, that’s a motivation or environment issue. Maybe the test suite takes 45 minutes and their manager is breathing down their neck. Your feedback needs to target the root cause, not the symptom.

The “Three Whys” Drill

Steal this from Toyota. When you spot a behavior you want to change, ask “why” three times. Not to the person—to yourself, first. “Why did they skip code review?” Because they were in a hurry. “Why were they in a hurry?” Because the sprint deadline was a fantasy. “Why was the deadline a fantasy?” Because the product manager promised a feature without talking to engineering. Now your feedback isn’t about the individual—it’s about the process that set them up to fail. That’s a conversation people can actually engage with instead of just surviving.

Team gathered around a whiteboard discussing a process flow

Step Two: Make It About the Work, Not the Worker

This is where most feedback jumps the shark. The moment you say “You are disorganized,” you’ve made it personal. Their brain flips into fight-or-flight mode. They’re not listening to your solution; they’re constructing a legal defense. Instead, anchor everything to observable behavior and its impact. “The last three pull requests had missing test coverage, which caused two production rollbacks.” That’s a fact. It’s not about their character—it’s about a pattern with consequences.

Engineers respect data. Give them data. “I’ve noticed that in standups, you often interrupt others. Yesterday it happened three times, and two people stopped sharing updates afterward.” Now you’re not saying “you’re rude.” You’re saying “here’s a specific action, here’s the frequency, here’s the effect on the team.” That’s a bug report, not a personal attack. And we’re actually good at bug reports.

Drop the Sandwich Method

The “compliment-criticism-compliment” sandwich is a lie. People see through it instantly. It trains them to dread praise because they know a “but” is lurking around the corner. It also dilutes the message. If you need to pad criticism with fake niceties, you’re not confident in your feedback—or you’re trying to manipulate emotions instead of solving a problem. Just be direct. “Hey, I want to talk about the code review delays. This is important because it’s blocking the team. Can we figure out what’s getting in the way?” No sugar, no venom. Just clarity.

Step Three: Co-Create the Solution

Feedback without a path forward is just complaining. The goal isn’t to make someone feel bad—it’s to change a behavior. And behavior change sticks when the person owns the solution. So after you’ve laid out the observation and impact, shut up and ask: “What do you think is going on here?” or “How would you approach fixing this?”

This does two things. First, it checks your diagnosis. Maybe you missed something. Maybe they’re dealing with a personal crisis, or the tooling is even worse than you thought. Second, it engages their problem-solving brain—the part that actually enjoys debugging. When they design the fix, they’re invested in it. They’re not following orders; they’re improving a system. That’s a completely different psychological state.

If they’re stuck, offer options, not commands. “One thing that’s worked for others is setting a personal reminder to run tests before pushing. Or we could pair on setting up a pre-commit hook. What sounds useful?” You’re a consultant, not a dictator. And frankly, you’ll get better results.

Two colleagues collaborating on a laptop, one pointing at the screen

Step Four: Time It Like a Deploy

Timing is everything. Giving feedback when someone is stressed, hungry, or publicly embarrassed is like deploying on a Friday afternoon—you’re begging for an outage. The best feedback happens in private, soon after the event, when both of you are calm. “Soon” means within 24-48 hours. Wait longer, and the details get fuzzy, the emotional charge fades, and it feels like you’ve been nursing a grudge.

Also, ask for permission. Not in a weird, formal way—just a quick “Do you have a few minutes to talk about something I noticed in the sprint review?” This respects their autonomy and lets them brace mentally. If they say no, respect that, but schedule a time. Forcing feedback on someone who’s not ready is a power move, not a help move.

Public Praise, Private Criticism

This rule is ancient for a reason. Criticizing someone in front of the team multiplies the shame by the number of eyeballs. Even if your words are perfect, the context poisons them. Save behavioral feedback for one-on-ones or private chats. Conversely, when someone does something right, say it loudly and in public. That builds a culture where feedback isn’t feared—because most of it is positive and visible.

Step Five: Follow Up or It Never Happened

One conversation rarely changes a habit. People need reinforcement, reminders, and sometimes course corrections. A week after the feedback, circle back. “How’s the test-running habit going? Anything still getting in the way?” This shows you’re not just dumping criticism and running—you’re actually invested in their improvement. It also gives you a chance to catch regressions early, before they become patterns again.

If they’ve improved, acknowledge it specifically. “I noticed your last three PRs had full test coverage and were on time. That’s made a real difference for the team’s velocity.” This isn’t flattery—it’s closing the feedback loop. It tells their brain “this new behavior is noticed and valued,” which is how habits actually stick.

When Feedback Goes Wrong: The Recovery Protocol

Sometimes you’ll screw up. You’ll be too harsh, too vague, or too public. The person will shut down or push back. Don’t double down. Don’t apologize so profusely that it becomes about your guilt. Just reset. “I think I delivered that poorly. Can we rewind and try again? What I actually care about is X, and I want to make sure we’re on the same side.”

This works because it models the very behavior you’re asking for: owning mistakes and fixing them. If you can’t take feedback on your feedback, you have no business giving it.

Building a Feedback Culture That Doesn’t Suck

Individual skill matters, but the environment matters more. If your team’s culture punishes honesty, even the best feedback techniques will fail. Here’s how to shift the culture from fragile to anti-fragile—where feedback actually makes the team stronger.

Normalize “Feedback” as a Neutral Word

In most teams, the word “feedback” triggers anxiety because it’s code for “you’re in trouble.” Change that. Start using the word for positive observations too. “Feedback on your presentation: the architecture diagram was crystal clear.” Make it routine. In one-on-ones, ask “What feedback do you have for me?” and take it seriously. When leaders model receiving feedback without defensiveness, it gives everyone else permission.

Kill the “Nice” Culture

“Nice” is the enemy of good. Teams that prioritize being nice over being honest end up with secret resentments and passive-aggressive code reviews. I’m not saying be a jerk—I’m saying be kind. Kindness is telling someone the hard truth because you respect them enough to believe they can handle it. Niceness is lying to them to avoid an awkward moment. Choose kind.

Make Feedback a Process, Not an Event

Annual performance reviews are where feedback goes to die. By the time you’re discussing something that happened in March, it’s November, and everyone has forgotten the context. Feedback should be continuous, lightweight, and tied to specific work. Code reviews, sprint retros, and project post-mortems are natural feedback mechanisms—use them. A retro where everyone says “what went well” and “what could be better” is feedback training wheels. It depersonalizes the conversation and makes improvement a team sport.

FAQ: Your Feedback Fears, Addressed

What if the person gets defensive no matter how I phrase it?

Defensiveness is often a sign of fear—fear of being judged, fear of consequences, or fear of looking incompetent. If it happens consistently, the problem might be the relationship, not the feedback. Have you built enough trust? Do they believe you’re on their side? If not, pause the feedback and work on the foundation. Ask them about their goals, their frustrations, what support they need. Once they see you as an ally, feedback becomes collaboration. If they’re still defensive, it might be a them-problem—but you can only control your half.

How do I give feedback to someone more senior or powerful?

Same principles, but with extra care on timing and framing. Senior people often get less honest feedback because everyone’s intimidated. That’s a disservice. Frame it as “I want to help you be even more effective” rather than “you’re doing something wrong.” Use data and impact on the team or project—senior folks usually care about those. And if they react poorly, that tells you something important about whether you want to keep working there.

Is it ever okay to give feedback in writing instead of face-to-face?

Yes, if it’s thoughtful and private. Some people process written feedback better because it gives them time to absorb without the pressure of an immediate reaction. But written feedback can also feel cold or permanent. If you go this route, be extra clear about your intent, use specific examples, and always offer to discuss in person afterward. Never give critical feedback in a public channel—that’s just a digital public shaming.

What if the behavior doesn’t change after multiple feedback sessions?

Then it’s no longer a feedback problem—it’s a performance or fit problem. Document the pattern, the feedback you’ve given, the support you’ve offered, and the lack of change. At that point, you’re not having a coaching conversation; you’re having a consequences conversation. “We’ve talked about this three times. The impact on the team is X. If this doesn’t change by Y date, we’ll need to move to Z.” It’s not personal—it’s protecting the team. And honestly, if someone can’t or won’t change a behavior that’s hurting the team, they might need a different team.

Feedback isn’t a soft skill. It’s a core engineering practice—like testing, like monitoring, like incident response. You don’t skip tests because they might hurt someone’s feelings. You don’t ignore a production bug because it’s awkward to mention. Treat behavioral issues with the same rigor you’d treat a memory leak. Diagnose, instrument, fix, verify. Do that, and you’ll build a team that doesn’t just ship code—it ships a culture where people actually grow.

Your Architecture Decisions Are Only as Good as the Documentation Around Them

Look, I’ve been around long enough to know most software architecture arguments are just theatre. You’ve got the whiteboard warriors sketching perfect hexagons while the rest of us wonder if they’ve ever actually deployed to production. But there’s one thing that separates the adults from the children in engineering, and it’s not your fancy event-sourcing pattern. It’s whether anyone—including you, six months from now—can figure out what the hell you were thinking.

Architecture decisions are social constructs. They’re bets we place with spotty information, and the only real currency is how well we communicate those bets. Without documentation that doesn’t make people want to bang their heads on the desk, your brilliant design is just a ghost haunting the codebase, scaring new hires and pushing senior engineers toward a drinking problem during on-call.

A person sketching a complex diagram on a whiteboard with sticky notes around it

The Architecture Decision Record: Your New Best Friend

I’m not talking about that auto-generated wiki some intern set up three years ago and nobody’s touched since. I’m talking about Architecture Decision Records—ADRs—a practice that’s been around since Michael Nygard wrote about it in 2011. If you haven’t read his original post, stop everything and go find it. I’ll wait.

ADRs are like the medical charts of your system. They lay out the context, the decision, and the fallout. Not the marketing fluff, not the aspirational architecture diagram that looks like a subway map designed by a committee of unicorns. Just the cold truth: “We chose option X because option Y would’ve meant rewriting half the monolith, and Bob was on vacation.” That’s the kind of honesty that saves necks.

Here’s the thing about engineering culture: we’re obsessed with being right, but we’re allergic to being understood. We’ll burn three weeks arguing Kafka versus RabbitMQ, but we won’t spend three hours writing down why we picked one. Then six months later, someone new joins, stares at the mess, and kicks off a Slack thread that replays the entire debate from scratch. That’s not engineering; that’s Groundhog Day with more caffeine.

What an ADR Actually Looks Like

It’s not a novel. It’s not a design doc that tries to predict the next five years of product roadmap. A decent ADR has four parts:

  • Title: A short name that doesn’t sound like a marketing bot spat it out. “ADR 001: We’re using PostgreSQL because we’re not insane” works fine.
  • Context: What problem were we solving? What constraints were we under? Was the CTO breathing down our necks because he read some blog post about microservices? Write it down.
  • Decision: What did we actually choose? Be specific. “We will use a relational database with read replicas” isn’t a decision; it’s a wish. “We will deploy PostgreSQL 14 on AWS RDS with at least two read replicas in us-east-1” is a decision.
  • Consequences: What got better? What got worse? Did we trade consistency for availability? Did we make the frontend team cry? Own it.

That’s it. You can slap on a status and a date if you’re feeling fancy, but the core is four sections that force you to think like an adult. I’ve seen teams stick ADRs straight into their repo next to the code, using a simple markdown file. No special tools, no Confluence pages that need a VPN and a prayer to access. Just text files that survive reorgs and tooling migrations.

A close-up of handwritten notes and diagrams on paper, showing technical sketches

Why Most Documentation Fails (And It’s Mostly Your Fault)

Let’s be honest: most documentation is written for the wrong crowd. Engineers write docs for themselves, or for some mythical architect who’s going to review the system with a checklist. But the real audience is the poor soul who joins the team in two years, opens the repo, and has zero clue why there’s a Redis cluster that seems to do nothing but cache cat memes.

Documentation fails when it’s too generic. “We follow microservices best practices” isn’t documentation; it’s a LinkedIn post. It fails when it’s too detailed, describing every class and method as if the code itself didn’t exist. And it fails most spectacularly when it’s out of date, because nothing kills trust faster than a diagram showing services that were decomissioned during the Obama administration.

The fix is simple, but it demands a culture shift. You need to treat documentation as part of the architecture process, not an afterthought. When you make a significant decision—say, choosing a message broker or deciding to split a service—writing the ADR is part of the work. It’s not something you do on Friday afternoon when your brain is fried. It’s the thing you do before you start coding, because if you can’t explain the decision clearly, you probably don’t understand it yourself.

The Real Technical Problem Is Ego

Here’s where I get blunt. The biggest barrier to decent architecture documentation is the ego of senior engineers. We’ve all met that person—the one who designs a system in their head, bangs it out in a caffeine-fueled sprint, and then acts annoyed when anyone asks questions. “Read the code,” they say, as if the code is Tolstoy and not a pile of spaghetti held together by hope and a few integration tests.

That attitude is a liability. It creates knowledge silos that turn into bus factors. When that engineer leaves—and they will, probably for a job with better pay and better snacks—they take the architecture with them. The rest of the team is stuck with a system nobody understands, and you start seeing commits that just add comments like “// don’t touch this, it breaks everything.”

Good documentation is an act of professional humility. It says, “I made this decision with the information I had, and I’m writing it down so you can judge me later.” It’s the opposite of job security through obscurity. It’s also the only way to have honest technical discussions. When a decision is written down with its context and consequences, you can argue about the trade-offs instead of arguing about what someone remembers from a meeting six months ago.

A team of engineers discussing a whiteboard filled with architecture diagrams and notes

From ADRs to Living Documentation

ADRs are just the start. Once you’ve got a habit of writing down decisions, you can build a lightweight documentation system that actually survives contact with reality. The key is to keep it close to the code and make it easy to update. I’ve seen teams use a /docs folder in the repo with a simple index, or a static site generator that pulls from markdown files. The tool doesn’t matter as much as the discipline.

One pattern I like is the “decision log” that’s part of the project’s README or a dedicated page. It lists every ADR with its status—proposed, accepted, superseded—so anyone can see the history of the system’s architecture at a glance. When a decision gets reversed or replaced, you don’t delete the old ADR; you mark it as superseded and link to the new one. That way, you’ve got a trail of how the thinking evolved, not just the final state.

This also helps with onboarding. Instead of handing new engineers a 50-page wiki that was last updated during the Trump administration, you hand them a list of decisions that explain why the system looks the way it does. They can read the ADRs, dig into the code, and actually get the trade-offs without having to corner a senior engineer in the kitchen and beg for context.

When Good Documentation Goes Bad

There’s a dark side to this, and I’ve seen it play out in teams that get too religious about documentation. You know the type: they turn ADRs into a bureaucratic process with templates, review boards, and a requirement that every decision be signed off by an “architecture council” that meets once a month and mostly argues about lunch orders. That’s not documentation; that’s performance art.

Documentation should be lightweight enough that it doesn’t feel like a chore. If writing an ADR takes more time than the decision itself, you’re doing it wrong. The goal is to capture the essence of the decision, not to produce a legal document you could submit as evidence in court. I’ve seen one-page ADRs that are more valuable than 30-page design docs because they actually get read and updated.

Another failure mode is documentation that’s too focused on the “what” and not the “why.” A diagram that shows service A calling service B is useless without context. Why does it call it synchronously? Why not use a queue? What were the latency requirements? The “why” is the part that ages well; the “what” is going to change next sprint anyway.

The Culture Shift Nobody Wants to Talk About

Here’s the uncomfortable truth: if your team doesn’t value documentation, it’s because your engineering culture has a problem. Not a tooling problem, not a process problem—a culture problem. Somewhere along the way, someone decided that writing things down is less important than shipping features, and now you’re paying the price in production incidents and wasted meetings.

Fixing this starts with leadership. If your tech lead or CTO doesn’t write ADRs and doesn’t ask for them, nobody else will. But it also requires a shift in how we evaluate engineering work. Right now, most performance reviews are based on code shipped, bugs fixed, features delivered. Nobody gets promoted for writing documentation that prevents a disaster two years later. That’s a failure of incentives, and it’s why most documentation is a wasteland.

I’ve seen one team experiment with making ADRs part of their definition of done. Before a story is complete, any significant architectural change had to have an ADR written and reviewed. It wasn’t heavy—just a quick check that the decision was documented. At first, people grumbled, but after a few months, it became a habit, and the team’s collective understanding of the system improved hugely. They spent less time in meetings explaining things and more time actually building.

What Happens When You Ignore This

Let me paint you a picture. You’re called into a production incident at 3 a.m. The database is melting, and nobody knows why. You trace the issue to a caching layer that was added two years ago by an engineer who’s now at a startup in Berlin. There’s no documentation, just a commit message that says “added cache.” The config is a mess of magic numbers, and nobody knows what happens if you tweak them. You spend four hours debugging, and by the time you fix it, you’ve lost a year of your life to stress.

That’s not a hypothetical. That’s a Tuesday in most engineering orgs. And it’s entirely preventable if someone had written down why the cache was added, what the eviction policy should be, and what the expected failure modes are. Instead, you’ve got a system held together by tribal knowledge and prayer.

The cost of bad documentation isn’t just the incident itself; it’s the slow erosion of trust in the system. Engineers start adding defensive code because they don’t understand the original intent. They duplicate functionality because they’re scared to modify existing components. The codebase becomes a museum of abandoned decisions, and nobody wants to be the curator.

FAQ: Because You Probably Still Have Excuses

“We’re too busy shipping features to write documentation.”

You’re too busy to save yourself time later? That’s like saying you’re too busy driving to change the oil. Documentation isn’t overhead; it’s an investment that pays off every time you avoid a redundant meeting or a production fire. If you’re constantly in crunch mode, that’s a sign your architecture is already a mess, and documentation is the first step to digging out.

“Our system changes too fast for documentation to keep up.”

Then your documentation is too detailed. Stop trying to document the current state of the code; document the decisions and the principles behind them. Principles don’t change every sprint, even if the implementation does. If your architecture is truly evolving that fast, ADRs for each significant change will actually help you track the evolution instead of losing the thread entirely.

“Nobody reads the documentation anyway.”

Nobody reads it because it’s useless. If your documentation is a graveyard of outdated PDFs and auto-generated nonsense, of course nobody reads it. But if you write ADRs that are concise, honest, and close to the code, people will read them—especially during incidents or onboarding. I’ve seen teams where new hires devour the ADR log because it’s the only thing that actually explains the system. Make it good, and they will come.

“Can’t we just use AI to generate documentation?”

No. Absolutely not. We’re not going there. Documentation is about human judgment and context, not about auto-generating paragraphs from code comments. If you’re relying on a tool to explain your decisions, you’ve already lost the plot.

The Bottom Line

Your architecture decisions are only as good as the documentation around them because architecture is a social activity. It’s about aligning a group of humans around a shared understanding of a system that’s too complex for any one person to hold in their head. Without that shared understanding, you don’t have an architecture; you have a collection of accidents held together by duct tape and hope.

So do yourself a favor. Next time you make a significant decision, write it down. Not in an email, not in a Slack thread that will vanish into the void, but in a file that lives with the code. Make it short, make it honest, and make it something your future self would thank you for. Because when the on-call pager goes off at 3 a.m., you’ll want to know why the hell someone chose that message queue, and you’ll want to know it fast.

Architecture isn’t about being right. It’s about being understood. And that starts with documentation that doesn’t treat your teammates like mind readers.