GAP·MAP
← all posts
July 11, 2026questions

Backend interview questions in 2026: the full map

A backend loop is not one interview, it is five or six smaller ones stacked back to back: a database round, an API round, an auth-and-security screen, a reliability discussion, usually a distributed-systems or system-design round, and a language-specific deep dive. Each has a flagship question the interviewer keeps in their pocket, and each flagship probes for the mechanism underneath. This post maps the territory and routes you into the lesson for each area rather than re-teaching it.

RoundThe flagship questionStudy
Database internals"The index exists. Why does the planner still do a seq scan?"db-indexing
Transactions"Snapshot isolation blocked the phantom. Why did the invariant still break?"transactions-isolation
API design"Two retries hit your POST with the same idempotency key at once. Now what?"api-design
Auth"We use JWTs. How do you log a user out right now?"auth-backend
Caching"One hot key expires under load. What happens to the database?"caching-strategies
Queues"Give me exactly-once delivery."message-queues
Distributed"During a partition, do you stay consistent or available?"distributed-fundamentals
System design"Design a URL shortener for 100M new links a day."backend-system-design

The database round

Half of most backend loops lives here. Query mechanics come first, and the SQL round has its own deep traps (the NOT IN plus NULL trap, the join-filter trap) covered elsewhere. Past syntax, the questions turn to what the engine does with your query.

"The index exists. Why does the planner still do a seq scan?"

Because the planner cost-compares. If it estimates that a large fraction of the table matches, jumping index to heap for every row loses to a straight sequential read. A low-selectivity column (a boolean, a status flag) or stale statistics produces the same result.

Trap the candidate says "the index is broken" or reaches for a query hint. The correct move is to read the plan and check estimated versus actual rows.

Column order is the sibling question. A composite index follows the leftmost-prefix rule, and equality columns must come before range columns.

-- query: WHERE tenant_id = 42 AND created_at > now() - interval '1 day'

-- WRONG: range column first; tenant_id can't be used as a clean seek
CREATE INDEX ON events (created_at, tenant_id);

-- RIGHT: equality before range
CREATE INDEX ON events (tenant_id, created_at);

"Snapshot isolation blocked the phantom. Why did the invariant still break?"

Write skew. Two transactions read an overlapping set, write disjoint rows, and both commit, and the invariant that spanned them is now violated. Snapshot isolation (Postgres Repeatable Read) forbids dirty, non-repeatable, and phantom reads, but it permits this. Only SERIALIZABLE (SSI) catches it, by aborting a victim with SQLSTATE 40001, which means the application must retry on that code.

The rest of the round grazes storage choices: normalization versus deliberate denormalization (schema design), embedding versus referencing when the store is document-shaped (NoSQL models), and what a bad shard key does to a system that has outgrown one box (database scaling).

Study Database indexing and transactions & isolation.

The API round

"Two retries hit your POST with the same idempotency key at once. Now what?"

A client that timed out retries, and both requests can arrive together. Check-then-insert races: both read no prior row, both process, and you charge the card twice. The fix is to let a uniqueness constraint arbitrate.

-- WRONG: check-then-insert; two concurrent requests both see nothing
SELECT * FROM idem WHERE key = $1;   -- both return empty, both process

-- RIGHT: unique index on key does the arbitration atomically
INSERT INTO idem (key, response) VALUES ($1, $2);  -- second one hits a
-- duplicate-key error, so it replays the stored response instead of re-running

Follow-up "Is that exactly-once?" No. It is at-most-once effect via dedup, and the side effect plus the key record must commit together or you dedup something that never landed. Pagination (cursor versus offset) and RFC 9457 error envelopes fill out the rest of the round.

Study API design.

Auth and security

"We use JWTs. How do you log a user out right now?"

You mostly cannot. A stateless JWT is valid until exp, with nothing server-side to delete unless you built it. The standard answer is a short-lived access token (5 to 15 minutes) plus a rotating refresh token, or a denylist of jti values in Redis, which reintroduces a per-request lookup and quietly makes your JWT stateful again.

Red flags "JWTs are encrypted, so we hide the role in there" (signed, not encrypted, the payload is public base64url), and reading alg from the token to pick the verification algorithm (the alg-confusion attack).

Security screens run parallel. SQL injection is fixed with prepared statements, not by escaping quotes, and "we use an ORM" is not immunity once raw fragments or an interpolated ORDER BY appear. IDOR is the authenticated-but-not-authorized bug: enforce access at the data layer, not the UI.

Study server-side auth and backend security.

Reliability and async

"One hot key expires under load. What happens to the database?"

A stampede. Every request misses at once and slams the database with the same query. Mitigations trade off: a per-key lock (singleflight), request coalescing, probabilistic early recomputation, or refresh-ahead.

Follow-up "Why delete the cache on a write instead of updating it?" Because updating races with a concurrent reader that already loaded the old value and writes it back stale.

Two neighbors round this out. Exactly-once delivery is impossible over an unreliable network (the ack can be lost after the work is done), so what you ship is at-least-once delivery plus an idempotent consumer, which is effectively-once. Kafka's exactly-once holds inside Kafka only. And retries: the naive "retry immediately, forever" turns a slow dependency into an outage, so you want backoff with jitter, a retry budget, and a circuit breaker that stops hammering a dead service.

Study caching, message queues, and resilience patterns.

Distributed systems and scale

The scaling questions start concrete: keep services stateless so any node can serve any request behind the load balancer, and offload reads to replicas while accepting that replication lag breaks read-your-writes. Then they go abstract. CAP forces a choice during a partition, C or A, because P is not optional on a real network. Once a system is split into services, the flagship is the saga: a distributed transaction replaced by local transactions with compensating actions, because one service owns one database and cannot join across the others.

Study scaling basics, distributed systems, and microservices vs monolith.

The system design round

"Design a URL shortener for 100M new links a day."

That is roughly 1,160 write QPS and 11,600 read QPS on average, and you design for peak, where the read path saturates first. What is graded is the method, not the diagram: clarify functional and non-functional requirements, quantify them, draw components, then name where the bottleneck moves at 10x. Every component you place answers to a requirement you stated out loud.

Study backend system design.

The rounds that decide ties

The remaining screens are shorter but they separate close candidates. Backend performance opens on the N+1 query (one query for the list, one per row) and how you batch it away. Concurrency wants the four Coffman conditions for a deadlock and optimistic versus pessimistic locking. Networking asks for the TLS handshake and why connection reuse matters for latency. Containers probes image layers and how a rolling update uses health checks. Observability asks what a trace shows that a log cannot, and backend testing asks what you mock and what you refuse to.

Red flags across the whole loop: asserting a component without tying it to a requirement, claiming exactly-once or strong consistency everywhere, "fixing" a race by adding a sleep, retrying a non-idempotent write with no idempotency key, and treating every system as if it needs sharding and six nines. Any one of them caps the round regardless of fluency. Pick the area you are weakest in above and run its diagnostic.

was this useful?

beta

The interviewer part is in the works.

The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.