Phantom Code AIPhantom Code AI
FeaturesEarn with UsMy WorkspacePricing
FeaturesEarn with UsMy WorkspacePricing

Interview Questions / Software Engineer

Software Engineer Interview Questions — DSA, System Design, and Behavioral by Level

Software engineer is the default interview track at every major tech company — from L3 (new grad) through L7+ (principal). The question types stay the same: data structures and algorithms, system design, behavioral. What changes is the weighting and the bar. This page collects original Q&A across the four buckets that decide every SWE loop, calibrated to where you sit on the ladder.

Universal across companies. The specifics differ between Google's hiring committee, Amazon's leadership principles, and Meta's coding cadence — but the underlying questions on this page are what you actually get asked.

How SWE interviews scale by level

Same loop structure on paper. Very different rubrics in practice.

L3 — Junior / new grad

Heavy weight on DSA fundamentals. Expect two to three coding rounds with medium LeetCode-style problems. System design is usually absent or a single very light round. Behavioral is short, focused on collaboration and learning speed. The bar is: can you solve a clean problem with a sensible approach, write working code, and reason about complexity? Hire signals here are raw coding ability and coachability, not scope or leadership.

L4 — Mid-level

DSA still dominates, but a simple system-design round enters the loop — something like "design a TinyURL" or "design a parking lot." Behavioral starts probing for ownership: a project you drove, a bug you tracked down, a disagreement you resolved. The bar shifts from "can you code" to "can you deliver a feature without supervision." Coding rounds expect cleaner code, better testing instincts, and faster recognition of standard patterns.

L5 — Senior

The senior loop is the most balanced. DSA stays — you'll still be asked to code a hard medium under time pressure. System design becomes serious: a full open-ended problem (design a feed, a chat system, a distributed cache) where the interviewer expects you to drive the conversation, surface trade-offs, and push into deep dives. Behavioral leadership matters: stories about leading projects, mentoring, cross-team influence. Many engineers stall at L5 not because of coding but because they can't tell sharp behavioral stories.

L6 — Staff

Coding rounds shrink — sometimes one, sometimes zero. System design expands into multiple rounds, often including a deep dive on a system you've actually built, plus an open-ended design. Scope and ambiguity are the central signals: can you take a vague problem, frame it, and produce a plan that other senior engineers will react to? Behavioral rounds probe org-level influence: did you change how a team builds, did you set technical direction, did you mentor other seniors? Staff is where the rubric becomes mostly non-coding.

L7+ — Principal and beyond

Mostly behavioral and strategic. Coding may be entirely absent or a single diagnostic round. The interview is about technical strategy at the organization level: setting multi-year direction, resolving cross-org technical disputes, deciding where the business should invest engineering capacity. System design rounds become architecture review rounds — you're asked to critique an existing design, find the load-bearing assumptions, and articulate what you would change. Stories at this level need to be about impact measurable at the company, not the team.

DSA fundamentals — Q&A

The patterns that show up in every coding interview. Eight questions covering the highest-yield techniques. If you can fluently recognize and apply these, you'll pass most L3–L5 coding rounds.

Q1.What is the two-pointer pattern, and when should you reach for it?

Two pointers is a technique where you maintain two indices into a sequence and move them based on a condition — usually one from each end, or both from the start at different speeds. It collapses what would be an O(n²) nested loop into a single O(n) pass. The classic case is finding a pair in a sorted array that sums to a target: place one pointer at index 0 and another at the last index, then move them inward depending on whether the current sum is below or above the target. The same shape solves container-with-most-water, three-sum (after sorting), and removing duplicates in place. The key precondition is some kind of monotonicity — usually a sorted array — that lets you discard half the search space with each step.

Q2.How does the sliding-window pattern work, and what problems does it solve?

A sliding window maintains a contiguous range [left, right] over an array or string, expanding the right edge to include new elements and contracting the left edge when a constraint is violated. It is the right tool whenever the question asks for the longest, shortest, or count of contiguous subarrays satisfying some property. The canonical example is the longest substring without repeating characters: extend right, store each character's last index in a hash map, and when you see a repeat, jump left to one past that index. Variable-size windows handle constraints like at-most-K distinct characters. Fixed-size windows handle things like maximum sum of any K consecutive elements. The window only moves forward, giving you O(n) overall.

Q3.When do you use BFS versus DFS on a graph or tree?

BFS explores level by level using a queue and is the default whenever you need the shortest path in an unweighted graph or the minimum number of steps to reach a state — word ladder, shortest bridge, rotting oranges, knight on a chessboard. DFS uses a stack (or recursion) and dives deep before backtracking. Reach for DFS when you need to enumerate paths, detect cycles, do topological sort, or compute connected components. On trees, DFS gives you elegant recursive solutions for subtree aggregates (max path sum, lowest common ancestor) while BFS is natural for level-order printing or right-side view. A good rule: if the question mentions shortest, fewest, or minimum steps, start with BFS; otherwise DFS is usually simpler.

Q4.How do you recognize a dynamic-programming problem and structure a solution?

DP applies when a problem has overlapping subproblems and optimal substructure — the same smaller question is asked many times, and the answer for size n can be built from answers for smaller sizes. The tell is wording like maximum, minimum, count the number of ways, or can you reach. Structure the solution in three steps: define the state precisely (e.g., dp[i] = longest increasing subsequence ending at index i), write the recurrence (dp[i] = 1 + max(dp[j]) for j < i where nums[j] < nums[i]), then choose top-down memoization or bottom-up tabulation. Classic warmups: climbing stairs, house robber, coin change, longest common subsequence, edit distance. Most interview DP problems are 1D or 2D state with a small constant of transitions.

Q5.How should you think about recursion in an interview, and when does it become problematic?

Recursion is the right model whenever a problem decomposes naturally into smaller versions of itself — trees, divide-and-conquer, backtracking, generating permutations or subsets. Define the base case, define what you return for a single subproblem, and trust the recursion to handle the rest. The trap is implicit stack depth: a recursive solution on a balanced tree of a million nodes is fine (depth ~20), but a recursive walk over a linked list of a million nodes will overflow. In Python the default limit is around 1000 frames. If depth is a concern, convert to iteration with an explicit stack, or rewrite tail-recursive calls as loops. Watch out for redundant recomputation — that is usually the signal to memoize and turn it into DP.

Q6.What is binary search beyond sorted arrays, and how does it generalize?

Binary search is not just for finding an element in a sorted array — it works on any monotonic predicate over a range. The pattern is: define a function check(x) that returns true for all x at or above some threshold, and false below it (or vice versa), then binary search the range to find the boundary. This shape solves problems like minimum capacity to ship packages in D days, smallest divisor given a sum constraint, or median of two sorted arrays. The hardest part is recognizing the monotonicity. Once you see it, the implementation is mechanical: maintain low and high, compute mid, call check(mid), shrink the half that cannot contain the answer. Watch off-by-one errors at the boundary — preferring [low, high) half-open ranges helps.

Q7.How does backtracking differ from brute force, and where does it shine?

Backtracking is brute force with pruning. You build a candidate solution incrementally, and as soon as the partial candidate cannot lead to a valid full solution, you abandon it and rewind. The framework is: choose, recurse, unchoose. It is the right tool for combinatorial search — N-queens, sudoku, generating all valid parentheses, word search in a grid, partition into K equal-sum subsets. The complexity is exponential in the worst case, but pruning often makes it tractable on real inputs. Two implementation tips: mutate a single shared state and undo on the way back rather than copying lists, and order your choices to put the most constrained ones first so failure happens early. That ordering can turn a TLE into a sub-second solution.

Q8.What's the role of heaps and priority queues in coding interviews?

A heap is the right data structure whenever the question asks for the K largest, K smallest, K closest, or anything where you repeatedly need the current min or max. Top-K problems are the canonical case: maintain a min-heap of size K; for each new element, push and pop if size exceeds K. The result is O(n log K) instead of O(n log n) full sort. Heaps also power Dijkstra's shortest path, the merge-K-sorted-lists pattern, and the running-median problem (one max-heap for the lower half, one min-heap for the upper half). Know that Python's heapq is a min-heap by default — to simulate a max-heap, push negated values. Custom comparators can be done by pushing tuples where the first element is the priority.

System design fundamentals — Q&A

Five canonical system design problems. The shape of the answer matters more than getting the "right" architecture — interviewers are scoring how you scope, estimate, decompose, and trade off.

Q9.How would you design a URL shortener like bit.ly?

Start with the functional requirements: shorten a long URL, redirect from a short URL, optionally support custom aliases and analytics. Capacity: assume 100M new URLs per month and 10x reads to writes — that's around 40 reads per second and 4 writes per second sustained, with peaks higher. For the short code, generate a 7-character base62 ID (62^7 ≈ 3.5 trillion combinations) either by hashing the long URL with a truncated MD5 or by using a counter run through a base62 encoder. The data model is a single table mapping short_code to long_url with created_at and optional expiry. Reads dominate, so cache hot mappings in Redis with an LRU policy. The redirect path is a 301 if you want browsers to cache it, or 302 if you want to track every click. Discuss collisions, custom alias conflicts, and how you'd shard by short_code hash if you outgrow a single database.

Q10.How would you design a distributed rate limiter?

Clarify scope first: per-user, per-IP, per-API-key, or per-endpoint? Then pick an algorithm. Token bucket is the most common: each user has a bucket with capacity C that refills at rate R tokens per second; each request consumes a token, and requests are denied when the bucket is empty. It allows bursts up to C while bounding the average rate. The state — current token count and last-refill timestamp — lives in Redis, keyed by user. Use a Lua script or Redis's atomic operations to make the read-modify-write race-free. For very high throughput, do approximate rate limiting at the edge with a local in-memory bucket per server, and reconcile periodically. Discuss the alternatives: fixed window (simple but suffers boundary spikes), sliding window log (accurate but memory-heavy), and sliding window counter (a good compromise). Always return a Retry-After header so clients can back off intelligently.

Q11.How would you design a distributed cache like Redis at scale?

The core idea is a cluster of in-memory key-value nodes, with keys partitioned across nodes by consistent hashing so that adding or removing a node only remaps a small fraction of keys. Each shard has a primary and one or more replicas for failover. Clients route requests using a hash ring, either at the client library or through a smart proxy. Eviction is LRU or LFU once memory is full, with optional per-key TTLs. For consistency, decide between cache-aside (application reads cache, falls back to DB on miss, then writes back) and write-through (writes go to cache and DB synchronously). Cache-aside is more common because it tolerates cache failures gracefully. Discuss thundering herd — when a hot key expires and a thousand requests stampede the database — and mitigations like request coalescing, probabilistic early refresh, or distributed locks on the refill path.

Q12.How would you design a pub/sub messaging system like Kafka?

Producers publish messages to named topics; consumers subscribe and receive them. Each topic is split into partitions, which are append-only logs replicated across brokers — partitioning is what gives you horizontal scale, replication is what gives you durability. Producers choose a partition either by round-robin or by hashing a key (so all messages for a given user land on the same partition and stay ordered). Consumers join a consumer group, and partitions are distributed across the group's members so each partition has exactly one active consumer in the group at a time. Each consumer tracks its offset per partition, which is what lets you replay history or reset a stream. Discuss delivery guarantees: at-most-once (commit offset before processing), at-least-once (commit after), and exactly-once (transactional writes). Cover retention by time or size, and how compacted topics work for state-like data where only the latest value per key matters.

Q13.How would you design a news feed for a social network?

Two extremes: pure pull and pure push. In pull (also called fan-out on read), when a user opens their feed, you query everyone they follow, merge their recent posts, and rank. It's simple and storage-light, but expensive at read time and bad if a user follows thousands. In push (fan-out on write), every time a user posts, you write a copy of that post into the feed of each follower. Reads become a single sorted lookup, but writes become massive for celebrities — one post can mean fan-out to 100M followers. The pragmatic answer is hybrid: push for normal users, pull for celebrities, and merge the two at read time. The feed itself lives in a sorted store keyed by user_id with timestamp scores. Layer ranking on top to mix recency, engagement, and relevance. Discuss caching the top N entries per active user in memory, and pagination via cursors rather than offsets so the feed stays stable as new posts arrive.

Behavioral leadership — Q&A

The five behavioral questions that decide most senior loops. Use STAR, but spend the time on Action and Result. Specific numbers and concrete decisions beat polished generalities.

Q14.Tell me about a project you led end-to-end.

The interviewer wants three things: scope (was this a real project with multiple people and weeks of effort, or a personal afternoon hack?), your specific contribution (what did you decide and execute, versus what did the team do?), and outcome (what changed measurably?). Use STAR — Situation, Task, Action, Result — but spend most of the time on Action and Result. A strong answer has shape: 'We had a 90-second p99 for the checkout flow, which was costing us measurable conversion. I owned the redesign across three services. I scoped the work into four milestones, drove the API contract reviews, wrote the migration plan, and personally rebuilt the bottleneck service. We landed it in eight weeks; p99 dropped to 12 seconds and conversion rose 4%.' Numbers, ownership, and a clean before/after. Avoid the passive 'we' that hides what you actually did.

Q15.Describe a technical decision you regretted, and what you'd do differently.

This question tests self-awareness and learning velocity. The trap is picking something so trivial that no growth is visible, or so catastrophic that it spooks the interviewer. Pick a real call — a framework choice, an architectural pattern, a build-versus-buy — that turned out wrong for reasons that were knowable at the time. Walk through the decision context, the trade-offs you weighed, the signal you missed, and what changed in your decision-making after. A strong example: 'I chose a single-table NoSQL schema for our event store because it scaled writes well, but I underestimated how many ad-hoc analytical queries the business would want. We ended up bolting on a separate warehouse anyway. Now I push earlier on access-pattern interviews with stakeholders before locking in a storage model.' The interviewer is looking for someone who can be wrong cleanly and update.

Q16.How do you handle disagreement with a senior engineer?

The wrong answers are 'I defer because they have more experience' (passive) and 'I push hard until they agree' (combative). The right answer shows that you separate the technical disagreement from the relationship and have a process for resolving it. First, make sure you understand their position by stating it back to them — often you find you were arguing past each other. Second, frame the disagreement as a shared question with shared criteria: what are we optimizing for, and what evidence would change either of our minds? Third, if the call is reversible and low cost, suggest running an experiment and measuring. If it's a one-way door, escalate to a written doc with both options laid out and let a third engineer or manager weigh in. Disagree-and-commit is the closing move: once a decision is made, support it fully, even if you argued the other side.

Q17.Tell me about a time you missed a deadline.

Almost everyone has missed a deadline. The interviewer cares about whether you saw it coming, who you communicated with, and what changed afterward. The worst answers blame other people or external chaos. A strong answer takes ownership of the planning miss: 'I committed to a four-week timeline on a search-relevance project. By week two I realized the data quality work I'd assumed was done was actually two weeks of cleanup. I told my manager and the stakeholders the day I knew, brought a revised plan with two cut-scope options, and we picked one. We landed two weeks late on the revised scope. After that I started building 25% buffer into estimates that depend on data I haven't personally inspected, and I now do a one-week spike on any unknown dependency before committing a date.' Owning, communicating early, and changing your process — that's the arc.

Q18.Describe a time you had to influence without authority.

This is a senior signal — the ability to drive change across teams you don't manage. Pick a story where you needed another team's work, didn't have org power, and got it done anyway. The mechanics are: build a clear written case for why the change matters to them (not just you), find allies on their team who agree before the formal ask, anchor the request to a metric or risk that their leadership already cares about, and offer to do part of the work yourself. Example: 'Our service was being throttled by a shared platform team's rate limit. I wrote a one-page doc with our usage projections, the customer-facing impact, and three options — including one where we'd contribute the engineering time. I socialized it 1:1 with two of their engineers first, then took it to their tech lead. They picked option two and we shipped together.' The shape is: writing, allies, shared metrics, shared work.

Mid-level / senior trade-offs — Q&A

The judgment questions that separate L4 from L5 and L5 from L6. Code review, mentoring, scope, and build-versus-buy. Not testing what you know — testing how you decide.

Q19.How do you approach code review as a senior engineer?

A senior code review is not a typo hunt. The first pass is the highest-leverage one: is this the right design? Does this change belong in this service, this layer, this abstraction? Catching architectural mismatch before the implementation is reviewed saves days of rework. The second pass is correctness: edge cases, error handling, concurrency, security. Only the third pass is style. Comments should be specific and actionable — 'this loop is O(n²) and the input can be 10K elements; please use a hash set' beats 'consider performance.' Distinguish blocking from non-blocking feedback: prefix nits with 'nit:' so the author knows what they can ignore. And review the test changes as carefully as the code changes — tests that pass with broken implementations are worse than no tests. Above all, be fast. A 24-hour review delay kills team velocity more than any individual review issue.

Q20.How do you mentor more junior engineers without doing the work for them?

The temptation when you can solve something in five minutes is to just solve it. That's a bad mentor move — it gets the ticket closed but leaves the junior no better off. The right pattern is to find the smallest scaffolding that lets them solve it themselves. Ask them what they've tried and where they're stuck specifically; usually the question reveals a single missing concept you can teach in two minutes. Pair on the first instance of a hard pattern, then have them do the next one solo. Code review is a primary mentoring channel — write the why, not just the what, in your comments, and link to docs or examples. Set them up with progressively harder projects: a bug, then a feature inside a known service, then a feature spanning two services, then a small design doc. The signal you're mentoring well is that they stop asking you the same kind of question twice.

Q21.How do you scope an ambiguous project?

Ambiguity is the senior tax. A junior gets a ticket; a senior gets 'figure out what we should do about latency.' The first move is always to write something down — even a half-page — and circulate it. The structure is: what problem are we solving, who is affected, what does success look like quantitatively, what are the options, what do we recommend and why, what are the risks. The act of writing forces you to find the gaps. Next, talk to three or four people: the person who raised the concern, an engineer who knows the system best, a downstream stakeholder who feels the impact, and your manager or tech lead. Each conversation will move the doc. Then propose a phased plan — usually a one-week investigation spike, then a milestone, then an MVP, then full scope. Senior engineers who can take vague input and produce a written plan others can react to are disproportionately valuable.

Q22.How do you decide what to build versus what to buy or open-source?

The default should be don't build it. Most internal tools that look special are 80% identical to a vendor or open-source equivalent, and the 20% you're tempted to customize is usually not worth the multi-year maintenance tail. The decision factors are: how core is this to your competitive advantage, how mature is the off-the-shelf option, what's the integration cost, and what's the lock-in risk. Build when it is genuinely your differentiator (the ranking algorithm at a search company, the inference stack at a model company). Buy when it is undifferentiated infrastructure (auth, payments, observability, log shipping). Open-source-and-fork is the worst of both — you carry maintenance without owning the roadmap. Frame the call in writing: total cost over three years including engineering time at full loaded cost, not just license fees. That comparison usually settles the debate.

Practice with PhantomCode

Reading questions is the first 10%. Practicing under interview pressure is the rest.

PhantomCode is an undetectable interview copilot that listens to your real interview and surfaces structured prompts in real time — coding hints during DSA rounds, architecture nudges during system design, STAR scaffolds during behavioral. The window is invisible to screen-share, so you can use it during a live loop. Available in 50+ spoken languages including English, Hindi, Mandarin, Spanish, Arabic, Portuguese, French, German, Japanese, Korean, and Tamil.

Interview Copilot — full loop coverageCoding Copilot — DSA-focused

Designed for software engineers interviewing at every level — L3 through L7+.