The Software Engineering Interview
Backend · Full-Stack · Systems
Software engineering interviews test problem-solving, CS fundamentals, and how you think under pressure. This guide breaks down what to expect and what actually matters — based on seeing hundreds of these from the hiring side.
What the interview process looks like
Most engineering interview loops follow a predictable structure. Knowing what's coming at each stage lets you prepare specifically, not generically.
Algorithms & Data Structures
What you actually need to know
The majority of interview problems use a small number of patterns. Once you recognise the pattern, the solution follows. Focus on these, in roughly this order:
- Arrays & hashmaps — most common. Two-sum variations, frequency counts, sliding window.
- Strings — palindromes, anagrams, parsing. Usually combine with hashmaps.
- Two pointers & sliding window — for sorted arrays, substring problems, or any "find the subarray" question.
- Trees & graphs — BFS and DFS. Know both iterative and recursive implementations. Understand when to use each.
- Binary search — not just on sorted arrays. Recognise when a problem has a monotonic condition you can binary search on.
- Dynamic programming — tabulation and memoisation. Start with 1D (climbing stairs, coin change) before 2D.
- Stacks & queues — bracket matching, monotonic stacks, BFS scaffolding.
How to approach a problem in the interview
- Clarify before coding. Ask about constraints, edge cases, input format. This is not stalling — it's what good engineers do.
- State a brute-force solution first. It shows you can solve the problem. Then ask yourself where the inefficiency is.
- Talk through your reasoning as you optimise. Silence is your enemy. Interviewers want to see how you think.
- State the time and space complexity before you're asked. Say it yourself: "This is O(n log n) time and O(n) space."
- Test with a simple example by hand before running it. Catch your own bugs.
Big-O — what you must know cold
- Array access O(1), search O(n), sorted binary search O(log n)
- HashMap get/put O(1) average, O(n) worst case
- Sorting O(n log n) — why quicksort is average-case optimal
- Tree traversal O(n) — every node visited once
- The tradeoff between time and space complexity — there's almost always one
System Design
The framework to follow
- Clarify requirements — functional (what the system does) and non-functional (scale, latency, availability). Never design before you know these.
- Estimate scale — daily active users → requests/second → storage requirements. Order-of-magnitude maths. Show you can think about scale concretely.
- High-level architecture — clients, load balancer, application servers, database, cache. Draw it. Label it. Explain each component's role.
- Deep-dive on key components — the interviewer will steer you here. Database schema, API design, the hard distributed systems problem specific to this system.
- Bottlenecks & improvements — where does this design break at 10x scale? What would you do? Show you can critique your own work.
Systems to practise
Work through these until the structure feels natural:
- URL shortener (simple CRUD, hashing, redirects, analytics)
- News feed / Twitter timeline (fan-out, caching, ranking)
- Rate limiter (token bucket, sliding window, distributed enforcement)
- Notification service (push/email/SMS, fan-out, deduplication)
- Search autocomplete (trie, prefix search, caching at CDN)
- File storage like Dropbox (chunking, deduplication, sync)
Core concepts to understand deeply
- SQL vs NoSQL — when each is appropriate. This comes up in almost every design interview.
- CAP theorem — consistency, availability, partition tolerance. You can only guarantee two. Know what this means practically.
- Caching — where to cache (client, CDN, app layer, DB layer), cache invalidation strategies, what to never cache.
- Message queues — async processing, decoupling services, handling spiky traffic, at-least-once delivery.
- Database replication & sharding — read replicas for read-heavy workloads, horizontal sharding for write scale.
- Consistent hashing — how distributed caches and load balancers distribute load without full rehashing.
OOP & Design Patterns
SOLID principles
These come up in technical discussions and code review scenarios. Know what they mean and — more importantly — when violating them causes real problems.
- S — Single Responsibility — one class, one reason to change. Violation leads to classes that are hard to test and impossible to reuse.
- O — Open/Closed — open for extension, closed for modification. Favour composition and interfaces over editing existing classes.
- L — Liskov Substitution — subclasses must behave correctly wherever the parent is expected. Violations break polymorphism.
- I — Interface Segregation — many specific interfaces beat one general-purpose one. Don't force consumers to implement methods they don't need.
- D — Dependency Inversion — depend on abstractions, not concretions. This is what makes code testable.
Design patterns that come up most
- Repository — abstraction over data access. Lets you swap databases or mock in tests.
- Strategy — swap algorithm implementations at runtime. Useful anywhere you have conditional behaviour.
- Observer / Event — decouple producers from consumers. Foundation of event-driven systems.
- Factory — centralise object creation. Useful when the exact type to create depends on runtime conditions.
- Decorator — add behaviour without modifying the original class. Used in middleware, logging, caching layers.
- Singleton — one instance, global access. Know it, but also know why it causes problems in tests.
Databases
What you need to know as a backend engineer
- Indexing — how B-trees work, why indexes speed up reads but slow down writes, when not to index (low cardinality columns, heavy write tables).
- ACID transactions — atomicity, consistency, isolation, durability. What isolation levels mean in practice (dirty reads, phantom reads, serializable).
- N+1 problem — fetching a list of records and then querying for each one individually. Recognise it, fix it with joins or eager loading.
- Query optimisation basics — EXPLAIN plans, index hints, avoiding SELECT *, keeping functions off indexed columns in WHERE clauses.
- Connection pooling — why you don't open a new DB connection per request, and what happens when the pool is exhausted.
Common questions
Tips from the hiring side
- They clarify before they code. Not to buy time — to actually understand the problem.
- They say "brute force would be X, but let me think about O(n log n)" rather than staring silently for three minutes.
- In system design, they lead the interview. They say "Let me start with requirements" and structure the session themselves.
- They catch their own bugs by walking through a concrete example before running the code.
- They know what they'd do differently. "Looking back, I'd have started with a cleaner abstraction here" is a sign of a senior engineer.
- They can explain a complex concept simply. If you can't explain it to a non-expert, you don't fully understand it.
- For coding: spend time on LeetCode patterns, not random problems. 100 problems with understanding beats 300 problems memorised.