How to use this guide
These ten concepts cover the majority of backend interview questions at every level. For each one you get the mental model, the diagram to keep in your head, the trade-offs, and the follow-up questions interviewers actually ask. If you can explain each section out loud in two minutes — including a failure story — you are in good shape.
1. HTTP & REST APIs
Everything a backend does starts with an HTTP request: a method, a path, headers, and maybe a body. REST is a set of conventions on top — resources named by URLs, verbs expressing intent, status codes expressing outcomes.
- Idempotency: GET, PUT, DELETE are idempotent; POST is not. This decides what clients may safely retry.
- Status codes are a contract: 2xx success, 3xx redirect, 4xx the caller's fault, 5xx yours. Don't return 200 with an error body.
- Statelessness: each request carries everything needed. That is what makes horizontal scaling possible.
Deeper reading: HTTP methods explained, REST API design, and status codes and headers.
2. Authentication vs Authorization
Authentication answers who are you? Authorization answers what are you allowed to do? They fail differently: 401 means "I don't know who you are", 403 means "I know who you are, and no."
- Sessions vs JWTs: sessions store state server-side (easy revocation, needs a store); JWTs carry signed claims (stateless, hard to revoke before expiry).
- OAuth 2.0 / OIDC: delegated authorization — the app gets a token from an identity provider instead of your password.
- Authorization models: roles (RBAC) for most apps, attributes or relationships (ABAC/ReBAC) when permissions get fine-grained.
3. SQL Indexing
An index is a separate sorted data structure — almost always a B+ tree — that maps a column's values to row locations. Without one, the database's only option is to read every row.
- Indexes are not free: every write now updates the table and each index. Write-heavy tables suffer under too many.
- Composite indexes follow the leftmost-prefix rule: an index on (a, b, c) helps queries on a, (a, b), and (a, b, c) — not on b alone.
- SELECT * defeats covering indexes: if the index contains every column the query needs, the table is never touched.
- Learn to read EXPLAIN: "Seq Scan" on a big table in a hot path is the finding; everything else is detail.
Deeper reading: Behind the scenes: database indexes and B+ trees and inverted indexing for search engines.
4. Database Transactions & ACID
A transaction groups statements so they succeed or fail as one unit. ACID is the guarantee set: Atomicity (all or nothing), Consistency (invariants hold), Isolation (concurrent transactions don't corrupt each other), Durability (committed means it survives a crash, thanks to the write-ahead log).
BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 'a'; -- debit UPDATE accounts SET balance = balance + 100 WHERE id = 'b'; -- credit COMMIT; -- either both happen, or neither does
| Isolation level | Anomalies prevented | Cost |
|---|---|---|
| Read committed | Dirty reads | Lowest; default in Postgres |
| Repeatable read | + non-repeatable reads | Moderate |
| Serializable | + phantom reads; full equivalence to serial execution | Highest; retries on conflict |
5. Caching & Cache Invalidation
A cache trades freshness for speed: keep hot data somewhere fast (usually Redis or in-process memory) so most requests never touch the database. The hard part is not storing values — it is knowing when they are wrong.
- TTL is your safety net: even if invalidation logic misses something, data self-corrects when the entry expires.
- Eviction policies: LRU is the default answer; LFU when frequency matters more than recency.
- Classic failure modes: cache stampede (a hot key expires and 1,000 requests hit the DB at once), cache penetration (queries for keys that don't exist), stale reads after writes.
Deeper reading: the cache-aside pattern and Redis explained.
6. Load Balancing
A load balancer spreads requests across identical server instances so no single one becomes the bottleneck — and so one dying instance doesn't take the site down.
- Algorithms: round-robin (simple), least-connections (better for uneven request costs), consistent hashing (when stickiness to a server matters).
- L4 vs L7: L4 balances on TCP/UDP (fast, blind to content); L7 sees HTTP and can route /api vs /static differently.
- Sticky sessions are a smell: they fight the statelessness that makes balancing work. Put session state in Redis instead.
7. Message Queues & Event-Driven Architecture
Instead of calling a slow or unreliable service synchronously, you publish a message and move on. Consumers process it at their own pace. You buy decoupling, buffering, and independent scaling — and you pay with eventual consistency and at-least-once delivery.
- Queues vs streams: a queue deletes after consumption (RabbitMQ, SQS); a log/stream retains and lets consumers replay (Kafka).
- At-least-once means duplicates: consumers must be idempotent — dedupe on event id.
- Ordering is per partition: key by aggregate id (e.g. order id) to get ordering where the domain needs it.
- Poison messages: after N failed attempts, route to a dead-letter queue and alert — or one bad message blocks everything behind it.
Deeper reading: event-driven architecture, honestly and Kafka explained.
8. Rate Limiting
Rate limiting caps how often a client can call you, protecting the system from bugs, abuse, and traffic spikes. The token bucket is the standard algorithm: tokens refill at a fixed rate, each request spends one, and an empty bucket means 429.
| Algorithm | Behavior | Use when |
|---|---|---|
| Token bucket | Steady rate + controlled bursts | General-purpose APIs (most common) |
| Leaky bucket | Smooths bursts into a constant outflow | Protecting a fragile downstream |
| Fixed window | Simple counter per window | Approximate limits; has boundary spikes |
| Sliding window log | Exact, no boundary spikes | Strict limits; more memory per key |
- Return
429withRetry-Afterso well-behaved clients back off correctly. - Limit per identity (user, API key, IP) — one bad actor shouldn't consume everyone else's capacity.
- In a distributed system, the counter lives in Redis or is approximated locally per instance.
Deeper reading: design a rate limiter and throttling explained.
9. Concurrency & Race Conditions
A race condition is any bug where the outcome depends on the timing of concurrent operations. The classic shape: two requests read the same value, both compute from it, both write — and one update silently disappears.
- Make the operation atomic:
UPDATE ... SET balance = balance - 60is one statement; the database serializes it for you. - Pessimistic locking:
SELECT ... FOR UPDATElocks the row until your transaction ends. Simple, correct, can bottleneck. - Optimistic concurrency: carry a version column; the update fails if someone changed the row since you read it. Retry on conflict.
- Idempotency keys: for "pay once" semantics across retries, dedupe on a client-supplied key.
Deeper reading: the idempotency pattern and distributed locks when one database isn't the whole story.
10. Retries, Timeouts & Circuit Breakers
Networks fail. The question is whether your system fails gracefully or amplifies the failure. These three mechanisms are the standard answer, and they only work together.
- Timeouts first: every outbound call needs one. Without it, a hung dependency holds your threads forever and one slow service takes down everything that calls it.
- Retries with exponential backoff + jitter: retry immediately and you hammer a struggling service; wait 100ms, 200ms, 400ms… plus randomness so retries don't synchronize. Only retry idempotent operations, or add idempotency keys.
- Circuit breaker: when failures cross a threshold, stop calling entirely for a cooldown — fail fast, give the dependency room to recover, then probe with a few requests.
Deeper reading: the circuit breaker pattern and DevOps concepts developers get wrong.
One-table cheat sheet
| Concept | One-line mental model | The follow-up to expect |
|---|---|---|
| HTTP & REST | Stateless requests, verbs + status codes as contract | Why is idempotency tied to retries? |
| AuthN vs AuthZ | Who you are vs what you may do; 401 vs 403 | How do you revoke a JWT? |
| SQL indexing | Sorted B+ tree shortcut; reads faster, writes slower | Leftmost-prefix rule? |
| ACID | All-or-nothing, crash-safe, isolated units of work | Dirty read vs phantom read? |
| Caching | Speed for freshness; TTL + invalidation strategy | How do you stop a stampede? |
| Load balancing | Spread traffic across healthy identical instances | L4 vs L7? Sticky sessions? |
| Message queues | Decouple with buffered, at-least-once delivery | How do you handle duplicates? |
| Rate limiting | Token bucket per identity; 429 + Retry-After | Distributed counters? |
| Race conditions | Timing-dependent bugs; fix with atomicity or locks | Optimistic vs pessimistic? |
| Retries & breakers | Timeout everything, back off, fail fast when down | What is a retry storm? |
If you can walk through each row with a real example from your own work — especially a time one of these broke in production — you will stand out far more than someone who memorized definitions.