Stop 20 · Interview PreparationTechnical · 2/8

Backend fundamentals

Part of the Full Stack Developer Roadmap

In short

The backend half of the interview checks whether you understand what happens behind the API: status codes, middleware, databases, transactions. Show the 'why', not just the syntax.

Being able to confidently explain Node.js, Express, and API design under interview pressure — the backend half of a full-stack interview.

The purple blob in a lab coat explains a bench of beakers and wires to an examiner with a clipboard.

Think of it like this

The practical exam viva

In the lab viva, the examiner points at your circuit and asks, "Why this resistor? What if it fails?" Getting the right reading isn't enough. Backend rounds are a viva on your server: explain each part and its failure.

Watch it happen

"Why would you use a transaction?"

Problem
Mechanism
Code
Failure
Proof

1/5Start with the problem: a wallet transfer is two updates. If only one happens, money appears or vanishes.

The big ideas

What you need to know

HTTP and Express

Methods, status codes, headers, middleware order, error handling and how a request flows through your app.

SQL that matters

JOINs, indexes, EXPLAIN, transactions and the N+1 problem. Know when NoSQL would be a better fit.

Node's event loop

Why one blocking loop freezes every request, and how async I/O lets one process serve many users.

Validation and errors

Validate input at the edge, return honest codes, never leak stack traces to clients.

See it in code

Walk through the code

ts
1app.post("/api/transfer", requireAuth, async (req, res) => {2  const { toId, amountPaise } = TransferSchema.parse(req.body);3  try {4    await db.$transaction(async (tx) => {5      const from = await tx.wallet.update({6        where: { userId: req.user.id },7        data: { balancePaise: { decrement: amountPaise } },8      });9      if (from.balancePaise < 0) throw new Error("INSUFFICIENT_FUNDS"); // rolls back the debit10      await tx.wallet.update({ where: { userId: toId }, data: { balancePaise: { increment: amountPaise } } });11    });12    res.json({ ok: true });13  } catch (e) {14    res.status(400).json({ error: { code: (e as Error).message } });15  }16});

1/4Validate the body first, so a negative or text amount never reaches the database.

An interactive Prisma transaction. Both wallet updates commit together, or the throw undoes everything.

Save yourself the pain

Common mistakes

Oops

Saying 'I'd use a transaction' without saying what it protects against.

Do this instead

Name the exact failure (crash between two writes, two requests at once) and how the design prevents it.

Oops

Returning 200 with an error message, or 500 for bad input.

Do this instead

Use 400 or 422 for bad input, 401 or 403 for auth problems, 404 for missing, 409 for conflicts.

Your mission

Backend viva practice

~40 min

Quick check

Without a transaction, your server debits wallet A and then crashes before crediting wallet B. What happens?

Go deeper

  1. 1Practice explaining the event loop, middleware, and REST conventions out loud, from memory.
  2. 2Do a live-coding practice session building a small API endpoint under time pressure.
  3. 3Review your weakest backend area specifically.

More technical at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge