cswork / libraryOpen practice workspace

Interview guides · Change

Change Software Engineer Interview Guide

Change Software Engineer interview guide: the three reported rounds, coding and system design practice, behavioral prompts and a seven-day prep plan.

The 60-second brief

The descriptions candidates see for Change do not name one product. They describe a spread of work, from user-facing applications to backend systems, built together with product managers and designers. For a Software Engineer, that translates to designing and writing software that meets user needs, taking part in code reviews, debugging live applications, and, depending on the team, building consumer-facing features or improving the scalability and performance of backend services.

This guide is for candidates applying for a Software Engineer role at Change. Candidates describe the requirements as a computer science degree or equivalent plus roughly 2-5 years of professional development experience, with Python, Java or JavaScript named as example languages and Git, Agile and Scrum listed as must-haves. The guide covers the three reported rounds, the coding, design, debugging and behavioral questions candidates report, and a plan for rehearsing them.

Candidates report three rounds over roughly 3-5 weeks: a Phone Screen, Technical Assessments covering coding challenges and system design discussions, and Onsite Interviews that run back to back and look at collaboration and team fit. Pace can vary by team.

Focus areas

  • Live coding
  • Software architecture
  • Scalability

Overview

The reported question list is broad rather than deep in any one area. It mixes classic coding problems (reverse a linked list, binary search, the longest substring without repeating characters, a dynamic programming problem, sorting large datasets), design discussions (a scalable web application, SQL versus NoSQL, REST API design, performance), engineering-practice questions (code quality, code review, refactoring, Git, estimation, requirements) and a long behavioral set. Candidates also list topic areas such as live coding, software architecture, scalability, programming language fundamentals and designing systems.

That breadth shapes preparation. Pick one language from the ones the role names (Python, Java or JavaScript) and use it for every coding exercise, so the syntax is automatic. Be able to write the linked-list reversal, binary search and sliding-window solutions from memory, state their complexity, and test them against empty, single-element and duplicate-heavy inputs. Example questions candidates mention also include the time complexity of common sorting algorithms and how a hash table works, so be ready to explain both without code.

For the design and architecture side, rehearse a repeatable structure instead of a memorized system: clarify users and traffic, separate the read path from the write path, choose storage and say why, add caching and queues where a bottleneck justifies them, and name what fails first. Do the same for REST API design (resources, status codes, idempotency, pagination, versioning) and for the SQL versus NoSQL comparison, where the useful answer is a decision rule tied to access patterns, not a list of features.

The behavioral material is a large share of the reported list and the final round is described as a look at collaboration and team fit. Prepare six to eight real stories (a conflict, a mistake, a refactor, a deadline squeeze, a disagreement with a product manager, a Git or release incident) and map each prompt to one of them, so you answer with evidence instead of general principles.

The Change interview process

Candidates describe three stages in this order, taking roughly 3-5 weeks end to end. Individual teams can change the pace, so confirm the exact format with your recruiter.

Phone Screen

Candidates describe the Phone Screen as an initial call about your background and fit for the role. No question list is tied to it, so treat it as the place to explain your experience clearly and to learn the shape of the remaining rounds. Expect to talk about the languages you work in, the projects you have shipped and why this role interests you, and be ready for a short technical conversation.

What to demonstrate

  • How clearly you describe your background and the work you have owned
  • Whether your experience fits the role as candidates describe its requirements
  • Basic technical communication, such as explaining a project or a language choice

How to prepare

  • Write a short walk through your career that ends at this role, naming the languages and the kinds of systems you built
  • Prepare a specific answer to which programming language you are most comfortable with and why, with a recent project as evidence
  • Have one concrete story about Git and code review ready, since version control and Agile practice are listed as must-haves
  • Ask the recruiter to confirm the number of rounds, their format and whether a take-home is part of the loop

Technical Assessments

Candidates report that Technical Assessments include coding challenges and system design discussions. That is the stage where the coding questions (linked list reversal, binary search, longest substring without repeating characters, sorting at scale, dynamic programming) and the design questions (a scalable web application, REST API design, SQL versus NoSQL, performance) are practised. Work the code aloud: restate the problem, give the simple solution, improve it, state complexity, and run your own test cases.

What to demonstrate

  • Working code for standard algorithm and data structure problems
  • Algorithmic reasoning, including time and space complexity
  • System design discussion, including scalability and storage trade-offs
  • How clearly you explain your choices while you work

How to prepare

  • Write the linked-list reversal (iterative), binary search and the sliding-window substring solution in your chosen language without references, then run them on edge cases
  • Practise one dynamic programming problem end to end: state definition, recurrence, base cases, then the space-optimised version
  • Outline a scalable web application on paper: clients, load balancer, stateless services, cache, database, queue, and the first bottleneck at ten times the traffic
  • Prepare a decision rule for SQL versus NoSQL and a checklist for REST API design covering resources, errors, idempotency, pagination and versioning

Onsite Interviews

Candidates describe the Onsite Interviews as several interviews back to back that look at collaboration and team fit. Since the format covers working with others, expect the behavioral prompts candidates report (difficult teammates, mistakes, prioritisation, disagreeing with a product manager) and prepare stories that show decisions you made and how you worked with product managers, designers and other engineers. Technical conversation can also appear, so keep your coding and design practice warm.

What to demonstrate

  • Collaboration with product managers, designers and other engineers
  • Team fit, as shown by how you describe conflict, feedback and shared goals
  • Judgment in practical scenarios such as debugging a live issue or estimating a project
  • Continued technical depth across coding and design topics

How to prepare

  • Build a table of eight stories (conflict, mistake, refactor, deadline pressure, disagreement with a product manager, Git incident, team alignment, motivation) and map each reported prompt to one story
  • Rehearse each story aloud in a Situation, Task, Action, Result shape, with the result stated as a measurable or observable change
  • Practise a debugging walk-through for a production issue: what changed, how you confirm impact, how you mitigate, how you find the cause
  • Prepare questions for the interviewers about how engineers, product managers and designers work together day to day

Where candidates lose points

Writing code in silence and only reading the finished solution at the end

Narrate in four steps: restate the problem, give the simple solution, improve it and state complexity, then run your own tests. This matters most for the linked-list, binary-search and longest-substring problems, where small off-by-one slips are easy to spot when you trace an example aloud.

Answering the design questions with a technology list instead of a structure

For a scalable web application or REST API, clarify users and load first, separate reads from writes, justify storage with the access pattern, and name the first bottleneck. For SQL versus NoSQL, give a decision rule tied to query shapes and consistency needs, not a feature comparison.

Giving a theoretical answer on code quality, code review or debugging

Tie each answer to a concrete practice: which tests you write and at what level, what you check in a review (correctness, readability, tests, risk), and the order of steps for a live incident (impact, recent change, mitigation, cause, prevention).

Telling behavioral stories where the team did everything and the result is unstated

Prepare eight stories in which your own decision is clear. State what you did, what it cost, and the result. Practise the mistake, difficult teammate and product manager disagreement stories most, because each can go wrong through blame or vagueness.

Being fluent in a language only on the surface when asked about language fundamentals

Choose one of Python, Java or JavaScript and be able to explain its core mechanics: how its hash table or dictionary behaves, how object-oriented and functional styles differ in it, and why you picked it. Be ready to compare it honestly with another.

Questions & practice

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Iterative three-pointer walk: prev = null, curr = head; on each step save next = curr.next, set curr.next = prev, then advance prev = curr and curr = next; return prev as the new head.
  2. Complexity: O(n) time and O(1) extra space, because every node is visited once and only pointers change.
  3. Recursive version: reverse the rest, then set head.next.next = head and head.next = null; it is O(n) time but O(n) call stack, so a long list can hit Python's default recursion limit of 1000.
  4. Edge cases to state and test: empty list, a single node, two nodes; verify by walking the result and checking the old head now points to null.

Follow-up

  • Reverse only the nodes between positions m and n in one pass.
  • Reverse the list in groups of k, leaving a shorter tail unchanged.
  • How would the code change for a doubly linked list?

How would you implement a binary search algorithm in your preferred programming language?

Medium · Coding / Algorithms

Approach

  1. On a sorted array keep an inclusive range lo = 0, hi = n - 1 and loop while lo <= hi: compute mid, return it on a match, otherwise set lo = mid + 1 or hi = mid - 1; return -1 when the range is empty. O(log n) time, O(1) space.
  2. Compute mid as lo + (hi - lo) / 2 in Java or C++: (lo + hi) / 2 can overflow int on very large arrays (the bug once found in the JDK's own binary search). Python integers do not overflow.
  3. For duplicates or an insertion point, write the lower-bound form on a half-open range [lo, hi): while lo < hi, if a[mid] < target then lo = mid + 1 else hi = mid; lo ends at the first index with a[lo] >= target. Python's bisect.bisect_left does this; Java's Arrays.binarySearch returns -(insertion point) - 1 when the key is absent.
  4. State the loop invariant to avoid off-by-one and infinite loops, and test: empty array, one element, target below the first or above the last element, all elements equal.
  5. Generalise: binary search works on any monotonic predicate, so it also finds the smallest answer that satisfies a condition (minimum capacity, minimum speed).

Follow-up

  • Return the first and last positions of a target that appears several times.
  • Search a sorted array that has been rotated at an unknown pivot.
  • Find the minimum ship capacity that delivers all packages within D days.

Create a program that finds the longest substring without repeating characters.

Medium · Coding / Algorithms

Approach

  1. Brute force checks every substring for repeats, O(n^3), or O(n^2) with a set per start index; name it, then improve with a sliding window.
  2. Keep a map from character to its last index and a left edge; for each right index, if the character was seen at an index >= left, move left to that index + 1; update the map and the best length right - left + 1.
  3. The '>= left' check is the classic bug: on "abba" without it, left jumps back when the second 'a' arrives and the answer comes out as 3 instead of 2.
  4. O(n) time because each index is processed once; O(min(n, alphabet size)) space for the map. A set-based window that removes from the left until the duplicate is gone is also O(n), since each character enters and leaves at most once.
  5. Edge cases: empty string returns 0, all-same characters return 1, the whole string distinct returns n; in JavaScript, characters outside the Basic Multilingual Plane are two UTF-16 code units, so iterate by code point if that matters.

Follow-up

  • Return the substring itself, not only its length.
  • Find the longest substring with at most k distinct characters.
  • How would you answer this for a stream of characters you cannot store?

Explain how you would optimize a sorting algorithm for large datasets.

Medium · Coding / Algorithms

Approach

  1. In memory, use the library sort and know what it is: Python's sort and Java's object sort are Timsort (stable, O(n log n) worst case, close to O(n) on input that is already mostly sorted); Java sorts primitive arrays with dual-pivot quicksort, which is not stable.
  2. Exploit the keys: integers or fixed-width keys in a bounded range can be sorted with counting or radix sort in O(n·k) without comparisons; sort small (key, pointer) pairs instead of moving large records to improve cache use.
  3. Data larger than memory: external merge sort. Read chunks that fit in RAM, sort each and write it as a run, then k-way merge the runs with a min-heap; each merge pass is O(N log k) comparisons and the real cost is sequential disk I/O.
  4. Across machines: sample keys to choose range partition boundaries so partitions are balanced, sort each partition in parallel, and concatenate in order (the approach behind distributed sorts such as Spark's sortByKey).
  5. Question whether a full sort is needed: top k uses a heap in O(n log k), a median uses quickselect in O(n) average, and stability matters only when you sort by several keys in sequence.

Follow-up

  • Sort 1 TB of records on a machine with 16 GB of RAM: walk through the passes.
  • You only need the top 100 of a billion values: what changes?
  • When would you accept an unstable sort?

Solve a problem using dynamic programming and explain your reasoning.

Medium · Coding / Algorithms

Approach

  1. Choose a problem and justify DP: overlapping subproblems plus optimal substructure. Coin change (fewest coins for an amount) is a good choice because it also shows why greedy fails: with coins {1, 3, 4} and amount 6, greedy picks 4 + 1 + 1 (3 coins) while 3 + 3 uses 2.
  2. Define the state and recurrence aloud: dp[a] is the fewest coins making amount a; dp[0] = 0, and dp[a] = min over coins c <= a of dp[a - c] + 1, with infinity for unreachable amounts and -1 returned if dp[amount] stays infinite.
  3. Pick the evaluation order: top-down recursion with memoisation is closest to the recurrence; bottom-up fills a table from small to large amounts and avoids recursion depth limits.
  4. Complexity is states times transition cost: O(amount × number of coins) time, O(amount) space. For two-dimensional problems such as longest common subsequence, keep only the previous row to cut space from O(m·n) to O(min(m, n)).
  5. Rebuild the actual answer by storing the choice made at each state, and test the edges: amount 0, an amount no coin combination can reach, a single coin type.

Follow-up

  • Count the number of ways to make the amount instead: why does putting coins in the outer loop count combinations rather than orderings?
  • How do you return which coins were used, not only how many?
  • How would you cut the memory of a two-dimensional table to one row?

Describe the trade-offs between SQL and NoSQL databases.

Medium · System Design / Architecture

Approach

  1. Relational: fixed schema, joins, ACID transactions across rows and tables, secondary indexes and a query planner that answers questions you did not anticipate; scaling is vertical plus read replicas, and sharding is largely your own work.
  2. NoSQL is several families, not one: key-value (Redis, DynamoDB), document (MongoDB), wide-column (Cassandra), graph (Neo4j). They model around known access patterns, denormalise, and partition horizontally by design.
  3. Consistency: many NoSQL stores default to or offer eventual consistency; Cassandra lets you tune it per query, and with replication factor N, reads and writes overlap when R + W > N. The line has blurred: MongoDB has multi-document transactions since 4.0, and PostgreSQL's JSONB stores schemaless documents with indexes.
  4. Decide from the workload: transactional data with relationships and ad hoc reporting (orders, accounts) fits SQL; very high write throughput with simple key lookups (sessions, event logs, feeds) fits key-value or wide-column. Name the partition key and the query it makes expensive.

Follow-up

  • Which would you choose for a user activity feed, and what would the partition key be?
  • How do you serve a query the NoSQL data model was not designed for?
  • What does eventual consistency look like to the end user, and how do you hide it?

Keep soft-deleted accounts from blocking re-registration

Easy · soft delete · unique constraints · engine differences

app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.

Approach

  1. Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
  2. Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
  3. For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
  4. State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.

Follow-up

  • A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
  • How do you honour an erasure request while resource_revision.actor_user_id still references this table?

What programming languages are you most comfortable with and why?

Medium · Technical / Domain Questions

Approach

  1. Lead with one primary language and tie it to a concrete project you shipped in it (size, what it ran, how long you maintained it); rank any second or third language by depth of real use rather than listing everything you have touched.
  2. Give the 'why' as language properties, not taste: for example Python for fast iteration and a standard library that covers interview staples (collections.deque, heapq, bisect), Java for static typing and JVM tooling, JavaScript or TypeScript for async I/O on a single-threaded event loop.
  3. Show you know the runtime underneath: CPython's default build has a GIL, so CPU-bound threads do not run in parallel and multiprocessing is the usual fix; Java generics are erased at runtime; in JavaScript, promise callbacks run as microtasks before the next macrotask.
  4. Name one honest limitation of your main language and how you work around it (dynamic typing caught with type hints plus mypy, verbose Java reduced with records), then say which language you will use in the coding stage and why.

Follow-up

  • What feature of that language would you keep out of production code, and why?
  • How does memory management work in it, and what kind of leak can still happen?
  • Which language would you avoid for a latency-sensitive service, and what would you pick instead?

Describe a challenging technical problem you solved and the approach you took.

Medium · Technical / Domain Questions

Approach

  1. Open with the measurable symptom and the stakes in two sentences (error rate, latency, data loss, a blocked launch), then state your own role with 'I' so ownership is clear.
  2. Walk the diagnosis as a sequence: what you measured first, which hypotheses you ruled out and with what evidence, and how you separated the root cause from a correlated symptom.
  3. Name at least two fixes you considered and the trade-off that decided it (cost, risk, time to ship, reversibility), so the choice reads as reasoning rather than luck.
  4. Close with evidence: before-and-after numbers, how you verified the fix held, and the guardrail you added (test, alert, runbook) so it could not silently return.

Follow-up

  • What alternative did you reject, and would it have worked?
  • How did you confirm the cause rather than a coincidence?
  • What would you do differently if the same problem appeared tomorrow?

How do you ensure the quality of your code?

Medium · Technical / Domain Questions

Approach

  1. Describe layers, cheapest first: formatter and linter (for example ESLint or ruff) plus a type checker (TypeScript, mypy) that run locally and in CI, so style and type errors never reach review.
  2. Tests shaped like a pyramid: many fast unit tests on pure logic, fewer integration tests at real boundaries (database, HTTP), a small number of end-to-end tests on critical flows; dependencies such as clocks and external APIs injected so tests stay deterministic.
  3. Treat coverage as a signal, not a target: a line can be executed with no assertion on its result, so look for untested branches and error paths instead of chasing a percentage.
  4. Small pull requests with a clear description, CI required to pass before merge, and review focused on design and correctness rather than formatting.
  5. After merge: feature flags or staged rollout, monitoring and alerts on the change, and a regression test written for every bug fixed.

Follow-up

  • How do you test code that depends on the current time or a third-party API?
  • What do you do about a flaky test that blocks the pipeline?
  • How much coverage is enough, and how would you decide for a given module?

Explain the difference between object-oriented and functional programming.

Medium · Technical / Domain Questions

Approach

  1. Object-oriented: state and the behaviour that changes it live together in objects; encapsulation hides the state, and polymorphism comes from dynamic dispatch on subtypes. Prefer composition over deep inheritance trees.
  2. Functional: pure functions (same input, same output, no side effects), immutable data, functions as first-class values, and composition through higher-order functions such as map, filter and reduce; side effects are pushed to the edges of the program.
  3. State the expression-problem trade-off: with classes it is easy to add a new type but adding a new operation touches every class; with functions over a closed set of data variants it is easy to add an operation but adding a variant touches every function.
  4. Practical consequences: pure functions are trivial to unit test and immutable data removes races on shared mutable state; the cost is copying, which persistent data structures reduce through structural sharing.
  5. Show both in one example in your language (Java streams, Python, JavaScript all mix the styles): a pricing rule as a class hierarchy versus a pure function over a record.

Follow-up

  • What makes a function pure, and why is it easier to test?
  • How would you model an order's state transitions in each style?
  • When does immutability cost too much, and what do you do then?

How would you design a scalable web application?

Medium · System Design / Architecture

Approach

  1. Start with requirements and rough numbers: users, requests per second at peak, read-to-write ratio, data size growth and latency target; these decide every later component.
  2. Stateless application servers behind a load balancer so you scale horizontally; sessions in a shared store such as Redis or in signed tokens; static assets on a CDN.
  3. Data tier: a primary relational database with read replicas for read-heavy traffic (mention replication lag and read-your-writes for a user who just saved), a cache-aside layer with TTLs and explicit invalidation, and sharding by a chosen key only when writes outgrow one primary.
  4. Move slow or bursty work (emails, image processing, reports) onto a message queue with workers and retries; add rate limiting and timeouts with circuit breakers on calls to dependencies.
  5. Observability and operations: metrics, logs and traces, health checks, autoscaling on a real signal, and rolling or blue-green deploys for zero downtime.

Follow-up

  • What breaks first at ten times the traffic, and how would you find out before users do?
  • How do you keep the cache consistent with the database on updates?
  • How would you shard the main table, and what query does that make expensive?

What considerations do you take into account when designing REST APIs?

Medium · System Design / Architecture

Approach

  1. Resources as nouns with HTTP methods carrying the verb; know the semantics: GET is safe and idempotent, PUT and DELETE are idempotent, POST is not, so retried POSTs need an idempotency key the server stores with the result.
  2. Status codes callers can branch on: 201 with a Location header on create, 400 or 422 for validation, 401 (not authenticated) versus 403 (not allowed), 404, 409 for conflicts, 429 with Retry-After for rate limits; one consistent error body with a machine-readable code.
  3. Pagination: cursor-based (keyset) over offset for large or changing lists, because offset skips or repeats rows when items are inserted and gets slower as the offset grows.
  4. Evolution and safety: versioning (path such as /v1 or a header), additive backward-compatible changes, optimistic concurrency with ETag and If-Match (412 on mismatch), authentication with bearer tokens over HTTPS, and per-client rate limits.

Follow-up

  • How do you make a payment-style POST safe for a client to retry after a timeout?
  • How would you paginate a list that changes while the client pages through it?
  • How do you remove a field without breaking existing clients?

Explain how you would handle system performance and optimization.

Medium · System Design / Architecture

Approach

  1. Measure before changing anything: define the target as percentiles (p95, p99 latency) and throughput, then find where time goes with tracing (APM) and profilers (py-spy, async-profiler, browser dev tools).
  2. Work by layer and fix the largest share first, since Amdahl's law caps the gain at the fraction you speed up: client and network (payload size, compression, CDN), application CPU, database, external calls.
  3. Database fixes come up most: read the plan with EXPLAIN ANALYZE, add or reshape indexes, remove N+1 query patterns by batching or eager loading, paginate unbounded queries, and pool connections.
  4. Then structural changes: cache hot reads with a clear invalidation rule, move slow work to a queue, parallelise independent calls, and scale horizontally once the code is efficient.
  5. Verify with a load test against the same percentiles, compare before and after, and keep a dashboard or alert so a regression is caught.

Follow-up

  • The p99 doubled while the average stayed flat: where do you look?
  • How do you decide a cache will help before you build it?
  • What would an EXPLAIN plan showing a sequential scan tell you, and what would you change?

If you were given a new feature to implement, how would you gather requirements?

Medium · Problem-Solving / Case Studies

Approach

  1. Start from the problem and the user, not the solution: who needs this, what they do today, and the metric that will show the feature worked.
  2. Turn functional needs into user stories with acceptance criteria, and ask for the non-functional ones explicitly: expected load, latency, security and privacy, accessibility, supported platforms.
  3. Walk the unhappy paths early: empty states, errors, permissions, partial failure, migration of existing data; these are where requirements are usually missing.
  4. List constraints and dependencies (other teams, APIs, data you need), write an explicit out-of-scope list, and confirm everything in a short written spec reviewed with the product manager and designer.
  5. Slice a first release that tests the core assumption, and agree how later changes to scope will be handled.

Follow-up

  • What do you do when the product manager and designer disagree on scope?
  • A requirement surfaces halfway through implementation: how do you handle it?
  • How do you decide what goes into the first release?

Describe your thought process when reviewing a peer’s code.

Medium · Problem-Solving / Case Studies

Approach

  1. Read the ticket and description first so you review against intent; if a change is too large to reason about, ask for it to be split before line-level comments.
  2. Review in order of cost to fix later: overall design and fit with existing code, then correctness (edge cases, null or empty input, error handling, concurrency), then tests that assert behaviour, then security (input validation, injection, secrets, authorisation), then performance (N+1 queries, unbounded loops).
  3. Leave formatting and style to linters and formatters so review time goes to things tools cannot catch.
  4. Write comments that are actionable and labelled: blocking versus nit, phrased as a question when you may be missing context, with a concrete alternative or a code suggestion; acknowledge what is done well.

Follow-up

  • The author disagrees with a blocking comment: what do you do?
  • How do you review a change of several thousand lines?
  • What does review catch that tests do not?

Discuss how you would estimate the time required for a new project.

Medium · Problem-Solving / Case Studies

Approach

  1. Break the work into tasks small enough to estimate (roughly a day or two each), including the non-coding work people forget: tests, code review, integration, deployment, migration, documentation.
  2. Estimate each task as a range; a three-point estimate weights it as (optimistic + 4 × most likely + pessimistic) / 6. Check the total against similar past projects (reference-class estimation).
  3. Find the unknowns and run a short spike on the riskiest one before committing; add an explicit buffer sized by risk rather than a hidden one.
  4. Give a range with a confidence level and the assumptions behind it, re-estimate at milestones, and when the date is fixed, negotiate scope rather than quality.

Follow-up

  • Halfway through, the estimate is clearly too low: what do you do and who do you tell?
  • How do you estimate work in a technology you have not used?
  • How do story points differ from time estimates, and when would you use each?

How would you approach debugging a production issue in a live application?

Medium · Problem-Solving / Case Studies

Approach

  1. Assess impact first (which users, how many, how severe) and communicate in the incident channel; mitigate before diagnosing if you can: roll back the latest deploy, turn off a feature flag, scale out or fail over.
  2. Bound the problem: when did it start, which endpoints, regions, versions or customers are affected and which are not; line the start time up against deploys, config changes, traffic spikes and dependency status.
  3. Move from metrics to logs to traces: error rates and latency show where, logs show what, a distributed trace shows which hop; check that the monitoring itself is not the thing that broke.
  4. Form one hypothesis at a time and test it with the least risky action; reproduce in staging with production-like data when the cause is unclear, rather than experimenting on live traffic.
  5. After the fix: confirm recovery on the same metrics, then write a blameless postmortem with root cause, timeline and action items (a test, an alert, a safer rollout step).

Follow-up

  • Rolling back did not fix it: what do you check next?
  • Only a subset of users is affected: how do you narrow it down?
  • What would you add so the same issue is caught before users notice?

Suggested practice checklist

The plan follows the three reported rounds and the question types candidates report: coding on days 2 and 3, design on days 4 and 5, practical judgment questions on day 6 and behavioral stories on day 7. Each day ends with something you can reread before the loop.

Day 1 — Map the loop and set your language

  • List the three reported rounds (Phone Screen, Technical Assessments, Onsite Interviews) and mark which question types each format covers: coding, design and collaboration
  • Choose one of Python, Java or JavaScript for all coding practice and write a short answer on why you are most comfortable in it
  • Write a short career walk-through ending at this role, with one project per major skill

Deliverable: A one-page loop map, a written language choice with reasons, and a career walk-through you can say aloud.

Day 2 — Core data-structure coding

  • Write the iterative and recursive linked-list reversal, then test the empty list, one node and two nodes
  • Write binary search with the lower-bound variant and trace it by hand on duplicates and a missing target
  • Explain aloud how a hash table works: hashing, collisions, load factor and resize

Deliverable: Three working solutions in your chosen language with a test list for each, plus a spoken hash table explanation.

Day 3 — Strings, sorting and dynamic programming

  • Solve the longest substring without repeating characters with a sliding window and a map of last-seen positions, then state complexity
  • Write a table of common sorting algorithms with time, space, stability and when each fits, then answer how to sort a dataset too big for memory
  • Solve one dynamic programming problem: define the state, write the recurrence and base cases, then reduce the space

Deliverable: Two working solutions, a sorting comparison table and a written state-and-recurrence note for the dynamic programming problem.

Day 4 — Design a scalable web application

  • Outline a scalable web application: clients, load balancer, stateless services, cache, database, queue, and where each helps
  • Write a REST API design checklist: resources, methods, status codes, error format, pagination, idempotency and versioning
  • Write a performance routine: measure first, find the slowest step, fix it, and re-measure

Deliverable: A one-page architecture sketch, a REST checklist and a performance routine, each usable as a spoken answer.

Day 5 — Storage, language fundamentals and code quality

  • Write a decision rule for SQL versus NoSQL tied to access patterns, consistency and growth, and try it on two example features
  • Prepare answers for object-oriented versus functional programming and for how you ensure code quality in your language

Deliverable: A written decision rule, a solved SQL practice question and two spoken answers on programming style and quality.

Day 6 — Practical judgment questions

  • Write the debugging routine for a production issue, with the first three things you would check
  • Write a requirements-gathering list for a new feature: users, success measure, constraints, edge cases and open questions
  • Prepare a code review checklist and a method for estimating a project, then select your most challenging technical problem story

Deliverable: A debugging routine, a requirements list, a review checklist, an estimation method and one technical story.

Day 7 — Behavioral stories, rehearsed aloud

  • Write eight stories: Git, refactor, difficult teammate, motivation, deadline prioritisation, mistake, team alignment and disagreement with a product manager
  • Say each story aloud in a Situation, Task, Action, Result shape, then cut it to its decision and result
  • Run one full mock: a coding problem, a design question and three behavioral prompts back to back

Deliverable: Eight story outlines, each mapped to a reported prompt, and notes from one full mock session.

Stories to prepare for Change

Candidates report a long behavioral set, and the final round is described as looking at collaboration and team fit. For a Software Engineer working with product managers, designers and other engineers, prepare stories that show your own decisions: how you handled conflict, ownership of a mistake, prioritisation, disagreement and shared goals.

What is your experience with version control systems, such as Git?

Medium · Technical / Domain Questions

Approach

  1. Answer with a specific repository story instead of a list of commands: team size, branching model (short-lived feature branches off main or trunk-based with flags), who reviewed, and how changes were merged.
  2. Show that you understand history, not only commands. Rebase a private feature branch to keep it linear before review, merge or squash for shared branches, and never rewrite history other people have already pulled.
  3. Have one recovery example ready: git revert for a bad commit already on main, git reflog to recover a lost commit, git bisect to find the commit that introduced a regression, and git push --force-with-lease instead of a plain force push.
  4. Describe conflict handling: read both sides to understand intent, rerun tests after resolving, and keep pull requests small so conflicts stay rare. Mention Agile practice here only if your team's process shaped how you branched or released.
  5. The answer that sinks it is 'I use Git every day' followed by commit, push and pull. Name something that went wrong or was hard and what you changed afterwards.

Follow-up

  • When would you merge instead of rebase, and why?
  • A bad commit is on main and already deployed. What do you do, step by step?
  • How would you find which commit broke a test that passed last week?

Discuss a time when you had to refactor existing code. What was your approach?

Medium · System Design / Architecture

Approach

  1. Pick a refactor where you chose the scope and the approach. Open with the pain in two sentences: what made the code hard to change, and what it cost (slow features, repeated bugs, hard onboarding).
  2. Explain how you made it safe: characterization tests that pin current behavior before you touch anything, then small, individually reviewable steps (extract function, introduce an interface, replace one caller at a time) rather than one large rewrite.
  3. State the blast radius controls: feature flags, a parallel run of old and new paths, a staged rollout, and the signal that would make you roll back.
  4. Close with the result: fewer defects in that module, faster changes, simpler tests, or reduced review time, with numbers only if you actually measured them. Say what you left alone on purpose.
  5. The common failure is a story where the refactor was a rewrite with no tests and no stated outcome. Show restraint and evidence.

Follow-up

  • How did you decide to refactor instead of leaving the code alone or rewriting it?
  • How did you prove behavior did not change?
  • What would you do if the team or a product manager wanted to delay the refactor?

Describe a time when you had to work with a difficult team member. How did you handle it?

Medium · Behavioral / Leadership

Approach

  1. Choose a real, mild-to-serious friction case where you were directly involved, and describe the behavior and its effect on the work, not the person's character. Avoid labels such as lazy or toxic.
  2. Show you talked to the person first and privately: you asked about their view, found the shared goal (shipping the feature, quality, the sprint), and agreed on specific changes such as review turnaround, written decisions or a clearer split of ownership.
  3. Say what you changed on your side too. A story where only the other person was at fault sounds incomplete.
  4. Describe escalation honestly: you involved a lead or manager only after direct conversation did not work, and you framed it as a delivery problem with facts.
  5. State the result: the working relationship, the delivery outcome, and what you do now to prevent the same pattern. The mistake that sinks it is blame without resolution.

Follow-up

  • What did the other person say when you raised it, and what did you learn from it?
  • What would you have done if the conversation had not helped?
  • Would you handle it differently now?

What motivates you to succeed in your role?

Medium · Behavioral / Leadership

Approach

  1. Give an honest, specific driver instead of a generic one. Good examples are watching users benefit from something you built, solving hard debugging problems, mentoring, or raising the quality of a codebase.
  2. Back each driver with a short example from your own work, such as the feature you shipped or the incident you resolved, so the claim is checkable.
  3. Connect the driver to the work in this role as candidates describe it: building features with product managers and designers, reviewing code, debugging and improving performance. Do not claim knowledge of the company's values that you do not have.
  4. Be honest about what drains you as well, and say how you manage it. A believable answer includes one trade-off.
  5. The mistake that sinks it is a vague answer such as 'I love challenges' or a driver that conflicts with the job, for example a preference for working alone when the role is collaborative.

Follow-up

  • Tell me about a time that motivation was tested. What did you do?
  • What kind of work would make you lose interest, and how do you deal with it?
  • How does this role fit what motivates you?

How do you prioritize tasks when faced with tight deadlines?

Medium · Behavioral / Leadership

Approach

  1. Start with the method, then prove it with one story. Method: list everything, size each item, rank by user or business impact against effort, and separate must-have from nice-to-have.
  2. Show scope negotiation instead of heroics: you cut or deferred items, agreed the trade-off with the product manager, and told stakeholders early what would slip rather than quietly working late.
  3. Include the engineering risk call: what you refused to cut (tests for the risky path, a rollback plan) and what you shipped smaller (a first version behind a flag).
  4. Give the result: what shipped, what was deferred and how it was tracked afterwards, and what you learned about estimating.
  5. The common failure is saying you work harder or longer. Show decisions, communication and the cost of what you dropped.

Follow-up

  • Two urgent tasks come from two different stakeholders. How do you choose?
  • What do you do when the deadline cannot be met even after cutting scope?
  • How do you stop deferred work from disappearing?

Tell me about a time you made a mistake in your work. How did you handle it?

Medium · Behavioral / Leadership

Approach

  1. Choose a real mistake with real consequences, such as a bad migration, a missed edge case that reached production, or a broken deploy, and own it in the first sentence. Do not pick a disguised strength.
  2. Walk through the response in order: how you noticed, how you limited the damage (rollback, flag off, hotfix), who you told and when, and how you confirmed it was fixed.
  3. Cover the cause and the prevention: the missing test, review check, alert or runbook step, and the specific change you made so the same mistake is harder to repeat.
  4. Keep the tone factual. Describe what you would do differently now with a concrete habit, such as a pre-deploy checklist or a staged rollout.
  5. The answer that sinks it is shifting blame, minimising the impact, or ending without any lasting change.

Follow-up

  • How did your team or manager react, and what did you do to rebuild confidence?
  • How would you have caught it before it reached production?
  • What process change came out of it, and did it stick?

How do you ensure that your team stays aligned with project goals?

Medium · Behavioral / Leadership

Approach

  1. Describe the concrete mechanisms you use, in order: a short written goal and definition of done at kickoff, a visible board or tracker, and a regular planning and retrospective rhythm if your team follows Agile or Scrum.
  2. Show how you catch drift early: demos of working increments, design notes or small design reviews before large work starts, and pull request descriptions that link back to the goal.
  3. Use one story where goals changed or two people understood a requirement differently, and say how you noticed and realigned, including the conversation with the product manager or designer.
  4. State the outcome: fewer surprises, faster reviews, or a feature that matched what users needed. Include one thing that did not work and what you adjusted.
  5. The mistake that sinks it is answering with 'regular meetings' alone. Name what artefact or habit makes alignment checkable.

Follow-up

  • How do you handle a teammate who is quietly working on the wrong thing?
  • What do you do when priorities change mid-project?
  • How do you make sure quieter teammates' concerns are heard?

How would you handle a situation where you disagree with a product manager’s vision?

Medium · Problem-Solving / Case Studies

Approach

  1. Begin by understanding the product manager's goal and evidence: what user problem or business target is behind the vision, and what you may not know (data, customer input, constraints).
  2. Show how you disagree: bring specific facts or a small prototype, offer two or three options with costs and risks, and frame the discussion around the shared goal instead of your preference.
  3. Include the decision rule: you commit to the decision if it is made with the information on the table (disagree and commit), and you record the risk and a signal that would justify revisiting it.
  4. Use a real story and state the result, whether you changed their mind, they changed yours, or you shipped their approach and the data later confirmed or refuted the concern.
  5. The mistake that sinks it is describing winning the argument or going around the product manager. Show respect, evidence and follow-through.

Follow-up

  • What if the product manager still disagreed after you showed the data?
  • When would you escalate, and to whom?
  • Tell me about a time you were wrong in this kind of disagreement.