Programming Fundamentals interview questions
Programming Fundamentals questions a Backend developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.
You have ten thousand orders and ten thousand customers in memory, and you need the customer name on every order. How do you put them together?
The strongest answer: Build a dictionary of customers keyed by id in one pass, then look each order’s customer up by key — two linear passes instead of scanning the customer list once per order
Why it works: Exactly — a hash lookup is roughly constant time, which turns a nested scan into two passes.
- Key it once, then look it up.
- Build a map keyed by the join id.
- One pass to build, one to read.
- Never scan a list inside a loop.
The interviewer asks: “Synchronous versus asynchronous I/O — when do you use which?” Strongest answer?
The strongest answer: Synchronous waits on this thread until the work finishes. Async frees the thread while I/O is in flight — HTTP, database, files. I don't sprinkle async on CPU-bound loops without a reason.
Why it works: Exactly. Async is about not blocking a worker while the disk or network answers. It is not a speed potion for CPU.
- Async = don't block the worker on I/O.
- Await the I/O you started.
- Parallel only when operations are independent.
- Never fire-and-forget a write.
The interviewer asks: “The user id isn't in the database. What does your code do?” Strongest answer?
The strongest answer: Treat missing as a case: return 404 (or a domain result), don't dereference a null. In C# that's nullable types / TryGet; same idea as Optional, None, or null checks in JS.
Why it works: Exactly. Absence is data. Map it to a 404 and a clear body. Crashes are for programming errors, not “row not found.”
- Missing row = 404, not a crash.
- Don't catch null-deref as control flow.
- Model optionality; don't default-fake it.
- Don't swallow errors into 200.
Why make a repository or a cache generic, rather than storing plain objects and casting on the way out?
The strongest answer: The type is checked when you compile, so putting the wrong thing in is a build error instead of a cast failure at runtime, and callers get the real type back without casting
Why it works: Right — a compile-time guarantee plus no cast at the call site. Errors move from production to the build.
- Type safety, checked at compile time.
- Let the compiler reject wrong types.
- No casts at the call site.
- Runtime cast errors are avoidable.
A reviewer says your new class should hold the base class instead of extending it. What is the argument, and when is inheritance still right?
The strongest answer: Composition lets the class hold the collaborators it needs and swap them; inheritance couples you to the parent’s state and invariants, so inherit only when the subtype really is the base type
Why it works: Exactly — the test is substitutability, not reuse. Shared code on its own is never a reason to inherit.
- Inherit for is-a, compose for has-a.
- Hold collaborators so you can swap them.
- Inheriting takes state and invariants too.
- Shared code alone is not inheritance.
Pods are being out-of-memory killed every few hours. The only recent change is a process-wide dictionary added to memoise a lookup by customer id.
What happened, and what rule do you set for the team?
The strongest answer: A process-wide map with no bound and no eviction grows with every distinct key until the heap runs out; every cache needs a size limit, an eviction policy and a size metric you can alert on
Why it works: Exactly — unbounded is the bug, not caching. A ceiling, an eviction policy and a metric turn a leak into a capacity decision.
- Every cache needs a ceiling.
- Bound the size; evict on a policy.
- Expire entries and export the size.
- A scheduled restart is not a fix.
The interviewer asks: “What do you look for when you hire a backend engineer?” Strongest answer?
The strongest answer: Judgement under failure: how they debug, how they talk about data integrity, how they say no to a dangerous shortcut. I use a realistic design or incident, not trivia recitation, and I watch whether they include operations and security in the happy path.
Why it works: Exactly. Senior backend is taste: transactions, failure, and the user-visible result. Trivia is a weak proxy.
- Hire for failure-mode judgement.
- Probe integrity, ops and security.
- Not trivia, not raw speed.
- Avoid “I don't need on-call” heroes.