Running technical interviews that actually predict job performance is one of the hardest skills to learn as an engineering leader. I've conducted hundreds of interviews across different platforms and teams, and I've seen firsthand how the wrong approach wastes everyone's time while the right one surfaces genuine talent. In this post, I'll walk you through the framework I've built over 5+ years—one that's helped us hire people who consistently deliver on day one.
Realistic problems — Work similar to the actual role beats puzzle questions
The first time I asked a candidate to invert a binary tree, I got a perfect solution in fifteen minutes. On their first sprint, they struggled to set up a PostgreSQL migration script and didn't know how to debug N+1 queries. That gap taught me everything I needed to know about how we were interviewing.
When you're hiring for a backend role building APIs, your interview should smell like that work. If your day job involves designing database schemas, handling concurrency, and writing query-optimized code, your interview should test exactly those muscles. The candidate won't just perform better—they'll walk away confident they understand what they're signing up for.
Here's what I mean by realistic:
- For backend roles: Give them a partial API codebase with a real-world bug (N+1 query, memory leak, race condition). Ask them to diagnose it, not build it from scratch.
- For frontend roles: Give them a component that works but feels janky. Ask them to profile it, identify the bottleneck, and explain their fix.
- For full-stack roles: Give them a feature request: "Users are complaining the checkout flow is slow." Walk through how they'd approach it end-to-end.
A concrete example: I once interviewed a senior engineer for a platform handling high-volume transactions. Instead of "design a cache," I gave them a simplified version of our actual trading engine with a known throughput bottleneck. They had 45 minutes to read the code, identify the problem, and propose a solution. They spotted the lock contention immediately and sketched out a sharding strategy. That told me they'd worked with similar systems. When they joined, they made meaningful contributions in week two.
The key is reducing the gap between interview and real work. Puzzles are fun, but they don't predict whether someone can refactor legacy code, work within your architectural constraints, or think through failure modes in production systems.
Structured rubrics — The same criteria for every candidate reduces bias
I used to score interviews in my head. One candidate was "solid" and another was "strong," but I'd struggle to articulate why, and comparing them directly was impossible. The result? I defaulted to hiring people who reminded me of myself, which is the opposite of building diverse teams.
A rubric changes that. It forces you to define what "good" looks like before you meet the candidate, and it makes every interview comparable.
Here's a rubric structure I've used successfully:
| Dimension | Poor (1) | Acceptable (2) | Good (3) | Excellent (4) |
|---|---|---|---|---|
| Problem decomposition | Jumps to code without clarifying the problem | Asks a few clarifying questions, then dives in | Breaks the problem into clear steps before coding | Proactively identifies edge cases and constraints |
| Code quality | Code is unreadable or has obvious bugs | Code works but has style or efficiency issues | Code is clean, readable, and reasonably efficient | Code reflects production standards; considers trade-offs |
| Communication | Silent or unclear; hard to follow reasoning | Explains some of their thinking | Clear explanations; easy to follow their logic | Asks clarifying questions; explains trade-offs explicitly |
| Collaboration | Dismisses feedback or suggestions | Accepts feedback but doesn't act on it | Incorporates feedback and adjusts approach | Seeks feedback; bounces ideas off the interviewer |
Every interviewer uses the same rubric. After the interview, you score independently—no discussion—then compare. When three interviewers give a candidate 3, 3, 2, you have data. When two give 4 and one gives 1, you know there's something worth digging into.
This removes gut feel. It also makes it easier to explain rejection to candidates: "We're looking for someone who can decompose complex problems independently, and we felt you needed more support there." That's actionable feedback, not "you weren't a culture fit."
Let them think aloud — How they reason matters as much as the answer
I once watched a candidate sit in silence for twenty minutes, then write perfect code. They got the answer right. But I had no idea how they thought, what trade-offs they considered, or whether they'd make the same decisions under pressure. I hired them anyway, and they turned out to be someone who froze in the codebase when asked to make unfamiliar architectural decisions.
Thinking aloud is a skill, and it's essential. When someone explains their reasoning as they go, you learn:
- Do they consider multiple approaches, or jump to the first solution?
- Do they know their tools and libraries, or are they guessing?
- Can they explain complex ideas clearly?
- How do they handle being stuck?
As an interviewer, you should encourage this early and often: "Walk me through what you're thinking right now." "Why did you choose that approach?" "What would you do differently if performance became the constraint?"
If they go silent, don't let it linger. A light prompt helps: "I notice you've paused—what's going through your head?" Most people appreciate the permission to think out loud. The ones who say "I need quiet to code" are telling you something real; some people genuinely work better that way. That's fine—just know it about them.
Here's a small example. A candidate was asked to implement a caching layer for an API endpoint. Instead of jumping to Redis, they asked:
"How often does this data change? Is stale data acceptable? What's our latency budget? Do we have Redis in production already?"
That sequence of questions told me they'd built production systems before. They weren't pattern-matching to "caching" and applying the standard solution. They were thinking about constraints and trade-offs. That's worth more than a perfect implementation of the wrong approach.
Sell the role too — Candidates are evaluating your team as well
An interview runs both directions. The candidate is deciding whether to spend 40 hours a week with you. If your process is sterile and transactional, you'll lose good people even if you offer the job.
During my interview, I spend the last ten minutes asking them about their concerns. "What would make this role a great fit for you?" "What's important in your next team?" "What are you skeptical about?" Good candidates have thoughtful answers. They're often skeptical of things you should be skeptical about too.
Use the interview to show what your team actually does:
- Share real work. "This is a real API request we've been debating for three weeks. What would you do?" It signals trust and gives them a window into how you think.
- Talk honestly about the tech stack. Not "we use cutting-edge microservices with Kubernetes and gRPC" (you probably don't), but "we run monolithic NestJS services on Docker, PostgreSQL for data, Redis for caching. It's boring, it works, we optimize when we have metrics."
- Discuss the hard parts. "Our codebase has some legacy patterns we're refactoring. How would you approach that?" Candidates who light up at that kind of challenge are your people. Ones who say "I'd rewrite it" might not be.
- Let them meet the team if possible. Even a 15-minute chat with future peers is worth more than anything you say about culture.
The best hire I've made said yes partly because I answered her question honestly: "What's the biggest technical debt here?" I didn't dodge it. I told her about our monolith, our migration strategy, and where we were in the timeline. She came because she wanted to solve that exact problem.
Common mistakes
Mistake 1: Asking what you can Google. "Explain the difference between async and await." Everyone knows this; their answer tells you whether they can regurgitate docs, not whether they can use it well. Instead: "Walk me through a scenario where you chose async/await over promises. What would happen without it?"
Mistake 2: Testing for your level, not theirs. I've seen mid-level interviews fail because the problem was a senior-level systems design challenge. Calibrate the difficulty. If you're hiring for a mid-level role, someone should be able to get 70% of the way with good reasoning, even if they don't finish perfectly.
Mistake 3: Interviewing for a role that doesn't exist. You're interviewing for "backend engineer," but your actual job is "backend engineer who can work on the iOS client and write SQL." Be honest. Either interview for the full scope, or hire specialists and let them specialize.
Mistake 4: Ignoring communication skills. Code quality doesn't matter if they can't explain their work in a pull request or onboard a junior. Communication is a first-class skill. Score it explicitly.
Mistake 5: Moving fast and hiring quickly. I've skipped the second interview to close a candidate faster. Every time, I regretted it. Take your time. A bad hire costs more than an unfilled position.
Key takeaways
- Design your interview to match real work. A candidate who excels at your actual job will perform better than one who aces abstract puzzles.
- Use a consistent rubric for every candidate. It reduces bias, makes comparisons objective, and gives you data instead of gut feel.
- Create space for thinking aloud. How someone reasons is as important as their answer. Encourage it early and stay curious about their logic.
- Remember you're being evaluated too. Use the interview to sell the role, show real work, and signal what it's like to be on your team.
- Calibrate difficulty to the role level. A good interview is challenging but achievable for the right person at that seniority.
- Score independently, compare afterwards. Avoid group-think. If scores differ wildly, dig into why.






Comments
Loading comments…