Portfolio/Writing/Why backend developers should not interview front-end candidates

Why backend developers should not interview front-end candidates

A light-hearted look at what goes wrong when the person grading your React interview thinks in for loops, distrusts arrow functions, and wants the time complexity of rendering a list. Plus the serious point: interview for the domain, by people who work in it.

You are twenty minutes into a front-end interview. You just solved the task with a clean .map() and a useMemo. The interviewer pauses, tilts their head, and says: "Okay, now do it with a normal for loop." That is the moment you realise a backend developer is running your front-end interview, and the next forty minutes are going to be about Big-O.

Disclaimer, said with love
This is affectionate ribbing. Backend developers are brilliant. They keep the money safe and the data consistent and the 3 a.m. pager quiet. They just should not be the ones deciding whether you understand closures.

The tells#

You can usually spot it within the first two questions. Some of the classics:

  • They accept your solution, then ask you to redo it "without the array methods".
  • They see an arrow function and ask, with genuine concern, "why is it a function that returns a function".
  • They treat useEffect like a cron job and ask how you would run it on a schedule.
  • They ask for the time complexity of a React re-render, nod slowly at your answer, and write "O(n)?" on the board with the question mark.
  • "Where does the state live" is a good question. "Could it live in Postgres" is a different kind of question.
  • They ask you to sort an array. You type .sort((a, b) => a - b). "Right, but which sort is that." Nobody knows. It is Timsort. They wanted merge sort on the whiteboard.
  • They are deeply suspicious of const and keep asking "but could it change though".
  • They ask you to avoid a library, watch you reimplement thirty percent of it, then mark you down for "not knowing about existing solutions".
  • They ask how you would cache the rendered output in Redis.
  • They ask you to reverse a linked list. There are no linked lists here. There has never been a linked list on the front end. The DOM is a tree and even that we try not to think about.
  • They see JSX and ask if it is "a templating language, like Jinja".
  • They ask about the thread safety of setState.
  • At some point, quietly, to themselves: "is CSS really that hard".

A representative transcript#

text
Interviewer:  Nice. Now solve it without map or filter.
You:          ...with a for loop?
Interviewer:  With a for loop.
You:          [does the for loop]
Interviewer:  Good. What's the time complexity?
You:          O(n). It's a list.
Interviewer:  And the re-render?
You:          The... re-render is also O(n)?
Interviewer:  [writes "O(n)??" on the board and underlines it twice]
Interviewer:  Where does the state live?
You:          In the component.
Interviewer:  Could it live in the database?
You:          It's whether a dropdown is open.
Interviewer:  So that's a no on Redis.
You:          That's a no on Redis.
Interviewer:  Last one. Reverse this linked list.
You:          [stares at the whiteboard, which shows a <ul>]

What they think they are testing#

Correctness. Problem solving. "Fundamentals." All reasonable things to want. The trouble is the mental model they are scoring against. A backend interview is often a fair proxy for backend work: given a hard algorithm or a nasty concurrency problem, can you reason it through. So they bring the same instrument to a front-end role and measure the wrong dimension with great precision.

What the job is actually made of#

A rough breakdown of where a front-end engineer's week goes:

  • Working out why a component renders forty-seven times when you type one character.
  • Deciding where a piece of state lives so it does not need to be threaded through six components.
  • Layout. Real layout. The kind where the design works until the German translation shows up.
  • Accessibility: focus order, roles, the keyboard model, announcing the thing that just changed.
  • Reading the network tab and killing a request waterfall.
  • Browser quirks: the iOS viewport height, the Safari date input, a hydration mismatch, a useEffect that fires twice in StrictMode and you have to be fine with that.
  • Bundle size, and the slow argument about which dependency has to go.
  • The flash of the wrong theme that you fixed with a script tag in the head, which is not a hack, please stop calling it a hack.
  • Sitting with a designer and turning "make it pop" into tokens.
  • Occasionally, a few times a year, an actual algorithm.

The Big-O detour#

Data structures and algorithms are not useless on the front end. They show up when you virtualise a huge list, diff two trees, or debounce a search. That is a handful of times a year. The daily complexity problem is "this re-renders on every keystroke because the parent passes a new array literal every render", which does have a cost, it is just not the one on the flashcards. Ask about that one.

Backend brain, front-end brain#

They askA front-end interviewer asksWhat the role needs
Reverse a linked listHere is a list that re-renders on every keystroke. Why, and how do you fix itRe-render reasoning, referential identity, memo boundaries
Time complexity of this loopThis form has four states. Walk me through loading, empty, error, and successState modelling, edge cases, honest empty states
Implement a hash mapDesign the props for a Select component someone else has to useAPI design, controlled vs uncontrolled, not leaking internals
How would you cache this in RedisWhen does this data go stale, and how do you invalidate itClient cache model, staleTime, invalidation on mutation
Do it without array methodsIs this accessible with a keyboard and a screen readerSemantics, focus management, ARIA only where needed

It is a domain mismatch, not an insult#

You would not put a front-end developer in charge of grading someone on lock contention, index selection, idempotency keys, or a partitioning strategy. They would ask if the database "has hooks" and whether you can just put the query in a useEffect. It would be unfair, and the hire would be bad, and nobody would be surprised.

Interview for the domain, run by people who work in the domain. The other direction is just as broken, we only notice this one because front-end people write blog posts about it.

When a backend dev in the room is fine#

  • The collaborative system-design round. A front-end and a backend engineer designing an API together is one of the best signals you can get. Can the candidate push back on a bad response shape, negotiate pagination, spot the field that should not be there.
  • The values and communication round. No domain required. Can this person disagree well, explain a decision, take feedback.
  • Shadowing. Sitting in on a front-end interview to learn the rubric before running one solo. Encouraged.

How to fix it#

  1. Front-end people run the front-end technical loop. This is most of the fix.
  2. If a backend engineer has to be in a technical round, hand them a rubric written by the front-end team, with acceptable answers listed. Including: "yes, .map() is the answer, no, they do not need to hand-roll it."
  3. Retire "implement debounce with a for loop". It measures whether someone revised last night.
  4. For what to actually assess, there is a whole post: React front-end interviews, what they assess.
Summary
A React interview run from a backend mental model measures the wrong thing carefully: for loops over .map(), Big-O over re-render behaviour, algorithms over state modelling, layout, and accessibility. It is a domain mismatch, not a competence gap, and it runs both ways. Put domain experts on the domain round, give anyone else a rubric, and keep the backend engineers where they are genuinely useful: the API design conversation, and telling you the linked-list question is fine for their loop, not yours.

Next up
Front-end architecture: the decisions that are expensive to change

Front-end architecture is not folder structure. It is the load-bearing choices: rendering strategy, app topology, the backend contract, where state lives, and the module boundaries. How to make those choices, enforce them, and evolve them.

Read next →