On this page
- What a backend loop is actually scoring
- The rounds, and what each one is really assessing
- API design: the signals interviewers listen for
- Data modeling: where correctness lives
- Concurrency and reliability: the round people fumble
- Worked example: design the API for a comments feature
- Common failures, and a weak-to-strong endpoint rewrite
What a backend loop is actually scoring
Who this is for
Anyone interviewing for a backend, platform, or API role and unsure what the rounds beyond "reverse a string" are looking for. Especially career switchers and new grads who can write code but haven't yet been graded on data integrity and concurrency.
Frontend interviews ask *can you build the thing users see?* Backend interviews ask *does your thing stay correct when nobody is watching?* The work is mostly invisible: a request comes in, data changes, a response goes out, and the test is whether that stays true under retries, partial failures, and two clients racing for the same row.
So the rounds skew toward state. You'll be judged less on clever algorithms and more on whether you reach for a transaction at the right moment, whether your endpoint is safe to call twice, and whether you can tell the difference between "slow" and "wrong." Knowing the shape of each round ahead of time is most of the battle.
Anyone can make a request succeed once. The job is making it succeed the second time it's accidentally sent, and fail loudly the time it shouldn't have been sent at all.
The rounds, and what each one is really assessing
Loops vary, but a backend loop is usually drawn from this menu. The wording on the schedule ("systems", "practical", "coding") hides what's actually being scored, so map the label to the signal before you walk in.
| Round | What it assesses | How to prep |
|---|---|---|
| API design | Can you model resources, pick status codes, and design an endpoint that's safe to retry and easy to evolve? | Practice designing a small API out loud: resources, verbs, errors, pagination, versioning, auth. |
| Data modeling / SQL | Do you understand schemas, indexes, joins, and the cost of a query? Can you spot an N+1? | Write the schema for a feature, then write the queries. Explain why each index exists. |
| Concurrency + reliability | Do you reason about race conditions, retries, timeouts, and idempotency? Do you know what breaks under load? | Rehearse the failure modes: two writers on one row, a retried payment, a dropped network call. |
| DSA (sometimes) | Baseline problem-solving. Often lighter than at product companies, but not skippable. | Arrays, hash maps, two pointers, basic graph or tree traversal. Don't over-invest past medium. |
| Design this service | Can you take a vague prompt to a coherent API, data model, and failure plan within an hour? | Run timed mocks. Practice asking scoping questions before drawing anything. |
Pro tip
If the recruiter won't tell you which rounds you have, ask "how much of the loop is data and systems versus algorithms?" The answer tells you where to spend your last week.
API design: the signals interviewers listen for
An API-design round isn't a vocabulary quiz. The interviewer is listening for whether you make the boring-but-correct choices without being prompted. Each of these is a small signal, and they add up fast.
- Resource modeling. Nouns as resources, verbs as HTTP methods.
POST /comments,GET /comments/{id}, notPOST /createComment. Collections are plural and consistent. - Status codes that mean something.
201for a created resource,400for bad input,401vs403(not authenticated vs not allowed),404for missing,409for a conflict,422for valid-but-unprocessable.500is your fault, not the caller's. - Idempotency. A
GET,PUT, orDELETEcalled twice should leave the same state. A naivePOSTdoes not, so for unsafe creates you offer an idempotency key (more on this below). - Pagination. Never return an unbounded list. Cursor-based ("give me the next 20 after this token") survives inserts better than offset-based ("page 5"), which skips and duplicates rows as data shifts.
- Versioning. Decide how clients survive a breaking change: a version in the path, a header, or strict additive-only evolution. Have an answer; "we'd never break it" is not one.
- Auth and authorization. Who is this caller (authentication) and are they allowed to touch this resource (authorization)? Confusing the two is a real-world security bug, and interviewers probe for it.
The trap
Reaching for 200 OK on every response, including errors, with a { "success": false } body. It works, but it tells the interviewer you haven't thought about clients, caches, or proxies that read the status line. Let the status code carry the meaning.
Data modeling: where correctness lives
This round rewards people who treat the database as the source of truth, not a bucket. The recurring themes:
| Idea | What to say |
|---|---|
| Normalize vs denormalize | Default to normalized (no duplicated data, updates touch one place). Denormalize deliberately for read-heavy paths, and name the cost: now you own keeping the copies in sync. |
| Indexes | An index makes reads fast and writes slightly slower, and costs storage. Index the columns you filter and join on. "Add an index" is the answer to a slow query, not to every query. |
| The N+1 problem | One query for a list, then one more per row to fetch a relation, is N+1 queries for N rows. Fix with a join or a single batched "fetch all children for these parents" query. Naming this unprompted is a strong signal. |
| Transactions + isolation | Wrap multi-step writes that must all-or-nothing in a transaction. Know that isolation levels trade consistency for concurrency, and that lower levels permit anomalies like dirty or non-repeatable reads. |
| SQL vs NoSQL | Relational for structured data with relationships and transactions. Document or key-value for flexible shape, simple access patterns, and scale-out. Lead with the access pattern, not the brand name. |
Pro tip
When asked "would you use SQL or NoSQL?", never answer with a database name first. Answer with the access pattern: "reads are by user id and writes need a transaction, so I'd start relational." The choice falls out of the requirement.
Concurrency and reliability: the round people fumble
This is where backend interviews separate people. The setup is always the same: something happens more than once, or out of order, or halfway. Your job is to keep the data correct anyway. Walk through the core failure modes so none of them surprise you live.
- Race condition. Two requests read the same value, both add to it, both write back, and one update is silently lost. The fix is to make the read-modify-write atomic: a single
UPDATE ... SET count = count + 1, a transaction with the right locking, or an atomic operation in the store itself. - Locking. Pessimistic locking (
SELECT ... FOR UPDATE) holds the row so nobody else can touch it, safe but it serializes and can deadlock. Optimistic locking (a version column you check on write) lets work proceed and retries on conflict, better under low contention. Name the trade-off. - Idempotency keys. The client sends a unique key with an unsafe request. The server records it; if the same key arrives again (a retry, a double-click), it returns the original result instead of doing the work twice. This is how you make "charge this card" safe to retry.
- Retries + timeouts. Every network call needs a timeout, or one slow dependency stalls your whole service. Retries need backoff and a cap, or you turn a blip into a stampede. And retries are only safe on idempotent operations, which is why idempotency comes first.
- At-least-once vs exactly-once. Most real systems deliver at-least-once: a message can arrive twice, so consumers must be idempotent. "Exactly-once" usually means "at-least-once delivery plus idempotent processing," not magic. Saying this plainly reads as experience.
"It worked when I tested it" is true of almost every concurrency bug. They only appear when two things happen at the same time, which your single-threaded test never does.
Worked example: design the API for a comments feature
Here's the design round in miniature. The prompt is deliberately vague ("design the API for comments on a post"), and the first move is always to scope, not to draw. Follow the flow.
- 1
Scope before you design
Ask the boring questions. Threaded replies or flat? Edit and delete allowed? Roughly how many comments per post, ten or ten million? Who can read versus write? You're showing you don't build for scale nobody asked for, and don't miss scale they did.
- 2
Model the resources
Comments belong to a post:
GET /posts/{postId}/commentsto list,POST /posts/{postId}/commentsto create,PATCH /comments/{id}to edit,DELETE /comments/{id}to remove. Plural collections, ids in the path, verbs as methods. - 3
Design the create path to be safe to retry
POSTisn't naturally idempotent, so accept anIdempotency-Keyheader. If the same key returns, hand back the original comment instead of inserting a duplicate. Now a flaky network or a double-tap can't create two comments. - 4
Page the list, don't dump it
A popular post can have thousands of comments. Return a bounded page with a cursor:
GET /posts/{postId}/comments?limit=20&after={cursor}. Cursor over offset, so new comments arriving mid-scroll don't shift or duplicate rows. - 5
Pick status codes and errors deliberately
201with the created comment on success,400for a malformed body,401if not signed in,403if signed in but not allowed to comment,404if the post is gone,409if an idempotency key collides with a different request. - 6
Name what you'd watch in production
Close by mentioning the operational view: a
created_atindex for ordered reads, rate limiting on the create endpoint to blunt spam, and soft-delete (adeleted_atcolumn) so a removed comment doesn't orphan its replies. This signals you've operated a service, not just shipped one.
Pro tip
Narrate the trade-offs as you go. "I'll use cursor pagination here because the list changes while users scroll" is worth more than silently drawing the correct thing. The round scores your reasoning, not just your diagram.
Common failures, and a weak-to-strong endpoint rewrite
Most rejections in backend rounds aren't exotic. They're the same few misses, over and over:
- No error handling. The happy path works and the interview ends there. They wanted to see what happens when the input is bad, the dependency times out, or the row already exists.
- Ignoring data consistency. Two writes that should be one transaction, left as two. A retry that double-charges. A counter updated with read-then-write instead of an atomic increment.
- Designing for scale nobody asked for. Sharding and a message queue for a feature that will have a hundred users. Over-engineering reads as poor judgment, the same as under-engineering.
Weak endpoint design
POST /createComment Body: { postId, text } Response: 200 OK { success: true, comment } - Inserts a row, returns it. - No idempotency: a retry creates a duplicate. - GET /allComments?postId=1 returns every comment. - On any failure: 200 OK { success: false }.
Strong endpoint design
POST /posts/{postId}/comments Headers: Idempotency-Key: <uuid> Body: { text } Response: 201 Created { id, text, authorId, createdAt } - Idempotency-Key makes a retry safe: same key returns the original comment, no duplicate. - GET /posts/{postId}/comments?limit=20&after={cursor} returns a bounded, cursor-paginated page. - Errors carry real status codes: 400 bad body, 403 not allowed, 404 missing post, 409 key conflict.
- Resource-based path (
/posts/{postId}/comments) instead of an RPC verb (/createComment). The post id moves out of the body and into the URL where it belongs. 201for a created resource, not200for everything. Errors stop hiding inside a{ success: false }body and use the status line.- The idempotency key turns an unsafe create into a retry-safe one. This single change is often the difference between a pass and a fail.
- The list is paginated. "Return everything" is the answer that gets followed up with "and when there are a million rows?", and now you have an answer.
Walk in remembering this
- Backend rounds score correctness under retries and races, not clever algorithms.
- API design: resources as nouns, real status codes, idempotency, pagination, versioning, auth-vs-authz.
- Data modeling: normalize by default, index what you filter on, and name the N+1 before they do.
- Concurrency: make read-modify-write atomic, give unsafe writes an idempotency key, put a timeout on every call.
- In a design round, scope before you draw, and narrate every trade-off out loud.
- Don't build for scale you weren't asked about. Good judgment cuts both ways.
Reading is step one. Now do it for real.
When you're ready, the platform has live mock interviews and portfolio-grade capstone projects you can actually talk about.
Keep reading
This is general, educational career guidance, not legal, financial, immigration, or professional advice. Examples are illustrative and simplified. Norms vary widely by country, company, role, and over time, so always verify what applies to your own situation. Nothing here guarantees an interview, an offer, or any particular outcome.