Get started

Taking an assessment rather than buying one? This page is written for employers. Here is the page for candidates.

Software engineering · Mid level

How to assess a Backend Engineer

Backend defects are almost never wrong answers; they are correct answers produced at the wrong time, twice, or under a lock. The take-home screen runs against a few hundred fixture rows, single-threaded, with a database that is empty at the start of every run, so every failure mode that actually costs money — concurrency, partial failure, retry duplication, migration under load, a query whose cost is linear in a table that grows — is structurally invisible. Worse, assisted code is at its most convincing exactly here: a model produces idiomatic, well-named, plausible handlers that encode the common case beautifully and have no opinion whatsoever about what happens when the payment provider returns a 504 after the charge succeeded. A reviewer marking on output quality will rate that submission highly.

The backend engineer owns the part of the system where mistakes persist. A front-end defect is a bad afternoon; a backend defect writes itself into a database and is still there next quarter. That asymmetry should drive the whole screening design, and it almost never does.

Hour to hour the work is less glamorous than the job description: adding a field and working out how to backfill it, changing a query because a table grew, integrating a third-party service whose documentation is wrong, and deciding how much of an upstream failure to absorb and how much to propagate. The interesting part is nearly always temporal. Does this operation do the right thing if it runs twice? What is in the database if the process dies between these two statements? If we deploy this while the old version is still serving traffic, which of the two schemas is the code assuming? A mid-level engineer who has internalised those questions is worth a great deal more than one who writes tidier code, and the gap does not show up in a diff.

The top quartile is recognisable by what they do before writing anything. They look at how big the table is. They ask what the read pattern is. They find out whether the caller retries, and if so with what backoff, because that determines whether the endpoint needs an idempotency key or merely a unique constraint. They know the difference between an error the caller can act on and an error the caller can only log. None of that behaviour is expressible in a submitted artefact, because all of it happens before the artefact exists — and that is the single strongest argument for a monitored sandbox over a take-home. The sandbox records the order of work: what was opened first, whether the schema was read before the handler was written, how long was spent on the happy path versus the failure path.

Assistance has raised the floor on backend output and left the ceiling exactly where it was. Stack Overflow's 2025 survey found 84 percent of respondents using or planning to use AI tools, 46 percent distrusting the accuracy of what comes back against 33 percent trusting it, and 45.2 percent of the 31,476 who answered saying that debugging AI-generated code takes more time rather than less. Read those together and the hiring implication is direct: the scarce skill is no longer producing a plausible service, it is being able to tell whether a plausible service is correct — including one you did not write. That is a verification skill, and verification is the thing the CRUD take-home never asks for.

What the hiring manager is really trying to predict is the incident rate eighteen months out: how often this person's code will page someone at night, and whether the post-incident explanation will be "we did not consider that" or "we considered it and chose wrong". Both happen. Only the first one is a hiring failure.

The follow-up conversation about the candidate's own submission is where that prediction gets made. The questions are narrow and unanswerable by assembly: walk me through what is in the database if the process is killed here; this endpoint is called twice with the same body, what does the caller see; you added an index, what does it cost on write; which of your queries would you expect to be the first to become a problem, and at roughly what row count. A candidate who reasoned about state answers these in their own words, using the names of their own variables, and will often volunteer the weakness before being asked. A candidate who assembled the submission gives a general answer about best practice and cannot connect it to line 40 of their own file.

What the job actually needs

How people fail in this seat

What most employers do instead

CV screen, a timed algorithm test, then a take-home asking for a small CRUD API against a fixture dataset, marked on whether the endpoints return the expected JSON.

Backend defects are almost never wrong answers; they are correct answers produced at the wrong time, twice, or under a lock. The take-home screen runs against a few hundred fixture rows, single-threaded, with a database that is empty at the start of every run, so every failure mode that actually costs money — concurrency, partial failure, retry duplication, migration under load, a query whose cost is linear in a table that grows — is structurally invisible. Worse, assisted code is at its most convincing exactly here: a model produces idiomatic, well-named, plausible handlers that encode the common case beautifully and have no opinion whatsoever about what happens when the payment provider returns a 504 after the charge succeeded. A reviewer marking on output quality will rate that submission highly.

The assessment

About 85 minutes end to end.

The systems it runs in

A Node and TypeScript order service on PostgreSQL, brought up with Docker Compose, with a real migration tool, a seeded database the candidate can open in psql, and an outbound payment client modelled on Stripe's API including its automatic client-side retry behaviour. The supplied test suite is the project's own runner, and it is green against the naive implementation.

Python with FastAPI and Alembic, Java with Spring Boot and Flyway, C# with .NET and EF Core, or Go — all against PostgreSQL, which the Stack Overflow Developer Survey 2025 reports as the most used database, with MySQL and SQL Server available for buyers on those engines. The three planted facts — a retrying client, a refunds table with no unique constraint, and a provider observed returning 504 after the operation succeeded — exist unchanged in every one of those stacks, so the fork does not move when the language does.

Working speed is not scored. The naive implementation turns the supplied suite green quickly and double-refunds in production, which is the entire construction of t1. Rewarding a fast green run would score precisely the failure the fixture exists to catch, and the N+1 in the second half is likewise the quicker thing to write. What is reported instead, outside the weighted mean, is how long the candidate spent reading the repository before the first edit.

What the candidate actually does

TaskWhat happens
The endpoint that runs twice
coding_sandbox · 45 min
An existing order service, roughly two thousand lines, with a real schema and a seeded database. The ticket asks for one thing: add a refund endpoint that calls a payment provider and records the refund. Three facts are in the repository but not in the ticket, and none of them is highlighted. The provider client is configured with automatic retries. The refunds table has no unique constraint. And a comment in an adjacent module notes that the provider has been observed returning a 504 after the operation succeeded. The supplied test suite passes against a naive implementation, which is the fork: the cheap path makes the tests green and double-refunds in production; the correct path makes the operation idempotent — an idempotency key, a unique constraint, a status check before the call, or an explicit statement of which of those was chosen and why. A second, smaller piece of the ticket asks for a filter on the orders list; the fixture has four hundred rows and a comment stating production has forty million, and the obvious implementation is an N+1. AI assistance is permitted and logged throughout.
The backfill plan
written_artifact · 15 min
The refund feature needs a new non-null column on a table the candidate is told is large and hot. They write the deploy plan a colleague will execute: the sequence of steps, what the running code assumes at each step, and what happens if the process is interrupted between step two and step three. No template is given. The cheap answer is a single migration file; the correct answer is a sequence in which the application never assumes a schema it might not have.
Interview on your own service
live_call · 25 min
A spoken conversation with the candidate's own code on screen. The questions are narrow, first-person, and have no generic answer. The process is killed immediately after line 40 — what is in the database? This endpoint is called twice with the same body four milliseconds apart — what does the second caller see, and what does the customer see? You added an index; what did that cost on write, and how would you find out? Which of your queries becomes a problem first, and at roughly what row count? Then the requirement changes live: refunds must now be partial, and the same order can be refunded five times — talk me through what in your code is now wrong. The last question is the one that separates: it invalidates the assumption the generated shape was built on, and only the person who understood the shape can find the breakage in it.

The mark scheme

Each criterion is scored 1 to 5 against written anchors, and every score is reported with the excerpt that earned it. A criterion marked floored is reported as a finding rather than averaged into the total. The first is open; open any other to read its anchors in full.

Idempotency and retry safetyweight 0.3States the retry hazard before being asked about it, chooses a mechanism and says what it does not cover, and can describe the database state after an…
1 Implementation refunds twice when called twice. No unique constraint, no key, no status check. Does not mention the possibility when asked directly about the 504 case.
3 Handles duplication somewhere — a check before the call, or a constraint — but the check and the write are not atomic, and the candidate cannot say what happens if the process dies between them.
5 States the retry hazard before being asked about it, chooses a mechanism and says what it does not cover, and can describe the database state after an interruption at a named line of their own code.
Cost read from the data, not the fixtureweight 0.2Names the access pattern, names the index it depends on, and gives a row count at which their own implementation would need revisiting — with the reas…
1 Query is written against the four hundred fixture rows and issues one query per row. Row-count comment in the repository is never opened.
3 Avoids the N+1 but cannot say what the query costs or which index it uses; performance is asserted rather than reasoned.
5 Names the access pattern, names the index it depends on, and gives a row count at which their own implementation would need revisiting — with the reasoning, not a memorised threshold.
Migration safetyweight 0.2Sequences add-nullable, backfill in batches, dual-write, enforce, drop — or a defensible alternative — and states explicitly which schema the code ass…
1 One migration adds a non-null column with a default to a large hot table, in one deploy, with no statement about locking or about what the old code does when it arrives.
3 Splits the change into steps but the plan does not say what the running application assumes between them, or assumes both versions are never live at once.
5 Sequences add-nullable, backfill in batches, dual-write, enforce, drop — or a defensible alternative — and states explicitly which schema the code assumes at each step and what an interruption leaves behind.
Ownership of the submitted designweight 0.2Volunteers a weakness in their own submission before being asked, and under the partial-refunds change names the specific lines and the specific assum…
1 Cannot connect a general principle to a line of their own file. Answers the changed-requirement question with best practice rather than with what breaks in their code.
3 Explains most decisions in their own words; one section of the submission is described rather than defended.
5 Volunteers a weakness in their own submission before being asked, and under the partial-refunds change names the specific lines and the specific assumption that stop holding.
Failure handling at the boundaryweight 0.1Distinguishes provider failure before, during and after the side effect, and says which of the three the code cannot currently tell apart.
1 Provider call has no timeout and no failure branch; an exception is caught and swallowed so the test passes.
3 Errors propagate, with a distinction between what the caller can act on and what it can only log.
5 Distinguishes provider failure before, during and after the side effect, and says which of the three the code cannot currently tell apart.

How it is scored

Weighted mean of the five criteria, scored 1-5 against the anchors, each reported with the excerpt of code, plan text, or transcript that earned it. The two heaviest criteria are things a green test suite is blind to, which is the point of the design. A submission that passes every supplied test can score 2 overall and should.

Integrity

The log describes what happened. It does not produce a cheating verdict — the follow-up conversation is the control, because a statistical accusation is not something we would ask a reviewer to defend.

What you receive

Who decides

Recommended. A reviewer with backend experience confirms or overrides each score with a written reason. The idempotency criterion in particular should never be scored by pattern-matching for a keyword — several correct mechanisms exist and a candidate who chose a constraint over a key and can defend the choice scores a 5.

What this does not measure

This design does not measure algorithm recall, systems-design vocabulary, distributed-systems theory, or breadth of framework experience, and it does not measure speed. It also does not measure what someone would do with a real production incident at three in the morning, when the constraint is nerve rather than judgment; nothing remote observes that. Two fairness risks are live. The first is that idempotency reasoning is learned from having been burned, which correlates with having worked somewhere with real traffic — a candidate from a smaller company may reason correctly and hesitantly, and reviewers should score the reasoning, not the confidence. The second is that the fixture is in one language and one database, which advantages recent users of that stack; offer the fixture in more than one and hold the rubric constant across them, since none of the five criteria is language-specific. The spoken interview should be offered with captions, extra time, or in written form on request, and scored on content, never on fluency or accent.

The whole design turns on one property of the t1 fixture: the supplied tests pass against the wrong implementation. That is not a trick, it is the actual condition of backend work. Backend defects are rarely wrong answers; they are correct answers produced twice, or at the wrong moment, or under a lock. A refund endpoint that refunds correctly when called once and refunds twice when called twice is a green build and a chargeback, and every element of the standard screen — the algorithm round, the CRUD take-home marked on response shapes — is structurally incapable of telling the difference.

Assistance sharpens this rather than blunting it. Given the refund ticket, an assistant produces a clean, idiomatic, well-named handler that encodes the happy path beautifully and has no opinion whatsoever about a provider that returns 504 after the money moved. It is a good submission by every criterion a reviewer usually applies. So the design assumes that submission arrives, and then scores what the candidate can do with it: did they notice that the client retries, did they read that the refunds table has no unique constraint, did they open the comment in the adjacent module. Those three facts are in the repository and not in the ticket, exactly as they are at work, and finding them is a search behaviour the sandbox records and a diff does not.

The backfill plan is a written artefact rather than code because the failure it screens for is not a coding failure. Every engineer can write a migration file. The question is whether they can hold two versions of the application in their head at once — the one that has already deployed and the one still serving — and say which schema each of them assumes at each step. A plan that reads "add the column, backfill, make it non-null" is a plan that has never met a deploy that takes eleven minutes. The document is also the cheapest possible proxy for a real senior behaviour appearing early: writing instructions precise enough for someone else to execute at nine on a Tuesday morning.

The interview is where the delta between produced and understood gets priced, and the partial-refunds turn is the instrument. Up to that point a well-prepared candidate can narrate a generated design plausibly, because the design is coherent and they have had forty-five minutes to look at it. Changing the requirement out loud removes the coherence: one order can now be refunded five times, so a uniqueness assumption that was invisible while it held becomes the central fact. A candidate who reasoned about state finds it in about fifteen seconds and usually says "then my constraint is wrong" before finishing the sentence. A candidate who assembled the submission answers about idempotency in general and cannot say which of their own lines stops being true. Nobody can sit that segment on someone else's behalf, and it takes four minutes rather than the several hours of code review it would take to reach the same conclusion on paper.

What a hiring manager is buying with this design is a prediction about the incident rate eighteen months out — how often this person's code will page someone, and whether the post-incident sentence will be "we did not think of that" or "we thought about it and chose wrong." Only the first is a hiring failure, and it is the one this assessment is built to see coming.

Sources

Every figure on this page is traceable. Where a claim could not be sourced it is stated qualitatively instead.

  1. Stack Overflow, 2025 Developer Survey, Developers section, roughly 49,000 respondents worldwide, developer-type question answered by 43,560, https://survey.stackoverflow.co/2025/developers
  2. US Bureau of Labor Statistics, Occupational Outlook Handbook, Software Developers, Quality Assurance Analysts, and Testers, 2025, https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm
  3. Stack Overflow, 2025 Developer Survey, AI section, roughly 49,000 respondents worldwide, https://survey.stackoverflow.co/2025/ai

See what the employer actually receives. A full report for one role, with every score shown beside the excerpt that earned it, conduct findings reported rather than averaged, and a reviewer sign-off required before any decision. No form.

Read a sample reportOr talk to us about this role