Interview Prep

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.

1
Recruiter / initial screen — 30 min
Background, motivation, and a quick sense-check on experience. Sometimes includes 1–2 easy coding warm-ups. This is mostly a filter, not an evaluation.
2
Technical phone screen — 45–60 min
1–2 coding problems on a shared editor (CoderPad, HackerRank, etc.). Usually medium difficulty. They're assessing whether it's worth bringing you onsite.
3
Coding rounds — 2× 60 min
2–3 problems per session. Typically 1 easier warm-up + 1–2 medium-hard problems. You're being evaluated on correctness, approach, complexity, and communication.
4
System design — 60 min
Open-ended: "Design Twitter" or "Design a rate limiter." This is where seniority gets tested. Juniors often skip this round; mid and senior roles almost always include it.
5
Technical discussion + behavioral — 45 min
Past projects, architecture decisions, technical opinions, and team fit. The interviewer is imagining working with you every day.

Algorithms & Data Structures

The coding round filters most candidates. It's not about memorising solutions — it's about pattern recognition and thinking out loud.

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

This is where junior and senior candidates diverge completely. A junior gives you a box diagram. A senior asks the right questions first, then reasons about scale, failure modes, and tradeoffs.

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

Implement an LRU Cache with O(1) get and put operations.
HashMap + doubly linked list. This is the canonical LRU question — know it cold.
Given a list of intervals, merge all overlapping intervals.
Sort by start time. Iterate and extend the last interval if overlap. Classic greedy pattern.
Design a URL shortener. Walk me through your architecture.
Start with requirements, estimate QPS, design the hash/encode logic, then discuss storage, caching, analytics.
What's the difference between a process and a thread? When would you use each?
How would you scale a relational database that's becoming a bottleneck?
Cover read replicas, connection pooling, query optimisation, caching, eventual sharding. Show you think in layers.
Explain the SOLID principles. Give an example of a violation you've seen or fixed.
Find all permutations of a string. What's the time complexity?

Tips from the hiring side

What good candidates do differently
  • 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.