Interview guides · Acme Brick
Acme Brick Software Engineer Interview Guide
Acme Brick Software Engineer interview guide: the two reported rounds, reported questions with answer plans, and a seven-day preparation schedule.
The 60-second brief
Candidates describe the Acme Brick Software Engineer role as building and maintaining business applications that streamline internal processes and improve how customers engage with the company. Inventory management systems and customer-facing applications are the two product types named. The work is described as collaborative: engineers settle requirements and scope with product managers, review each other's code, test and debug, write technical documentation, and sometimes work on projects that span departments.
This guide is for software engineer candidates preparing for Acme Brick. It covers the two reported stages (an initial screening and the technical interviews), the reported question set across coding, system design, debugging, case-style problems and behavioral questions, and the languages, frameworks and databases the reported requirements list. The reported questions are a representative set that varies by team, so the guide teaches the technique behind each one instead of a single memorised answer.
Candidates report two stages over roughly 2-4 weeks: a screening conversation with an HR representative, then a technical stage made up of one or more interviews with engineering managers or team leads.
Focus areas
- Software Engineering (Role Responsibilities)
- Engineering Interview Communication
- Interpersonal Communication (HR to Engineering Hand-off)
Overview
The reported role is general application development. Candidates describe a requirement of one major language (Java, C# and Python are named), experience with web frameworks and REST APIs, working knowledge of SQL and NoSQL databases, Git, and sound problem-solving. Cloud platforms such as AWS or Azure, agile practice and CI/CD are listed as extras. Inventory systems and customer-facing applications are the examples given of what gets built, so a typical day mixes feature work, debugging and code review more than research-style algorithm work.
The reported question list is broad rather than deep. It spans language and engineering-practice questions (languages you know, code quality, object-oriented versus functional programming, version control), system design (high-volume transactions, scalability and reliability, microservices, data consistency), problem-solving cases (a latency spike, debugging a hard issue, web UX, features from user feedback, unclear requirements), classic coding (reverse a linked list, shortest path, a sorting algorithm, binary search, data-structure trade-offs) and behavioral prompts. Because candidates do not report which question belongs to which stage, prepare every type for the technical interviews.
Preparation therefore means building a short, honest answer for each category instead of going deep on one. Pick the language you will code in and be fluent in it, write the four classic coding problems by hand until they are correct on empty and single-element inputs, and rehearse design answers that begin with scope and numbers. Then prepare six or seven behavioral stories from your own work, each with your personal role and a measured result, because the screening and the technical stage can both include them.
The Acme Brick interview process
Candidates report two stages: a screening with an HR representative, then a technical stage that can involve several conversations with engineering managers or team leads. The structure is said to vary by team.
Initial Screening
Candidates describe the first stage as a screening with an HR representative about your background and how it fits the role. It is a conversation, so the work is making your CV line up with what the role asks for: one major language (Java, C# or Python), web frameworks and REST APIs, SQL and NoSQL databases, and Git. Have a clear account of why you want this kind of role and be ready to name the language and projects you would want to be judged on.
What to demonstrate
- How clearly you summarise your background and experience
- How well your experience matches the languages, frameworks and databases the role lists
- Whether your expectations and logistics are clear enough to plan the next stage
How to prepare
- Write a short CV walkthrough that goes project by project, naming the language, the framework and the database each one used, and what you personally built.
- Prepare your answer to the programming-languages question: pick one or two languages, and tie each to a project where you made a real decision.
- Prepare questions about the team, the applications it owns (for example internal business tools or customer-facing apps) and how the technical stage is organised.
Technical Interviews
Candidates describe one or more technical interviews with engineering managers or team leads, meant to assess technical capability. The reported question set that fits this stage spans language and engineering practice, system design, debugging and case-style problems, coding and algorithms, and behavioral questions. Which question lands in which conversation is not reported, so prepare to code on a shared editor or whiteboard, to talk through a design with numbers, and to tell a behavioral story in the same sitting. Say your reasoning aloud as you go.
What to demonstrate
- Technical capability across the languages, frameworks and databases you list
- Working code and clear reasoning on the classic algorithm questions
- Design and debugging reasoning on open-ended questions such as a latency spike
- Collaboration and communication as shown in your behavioral stories
How to prepare
- Implement reversing a linked list, binary search and a sorting algorithm from memory, and trace each on an empty input and a single element.
- Rehearse one design answer (millions of transactions per second) and one debugging answer (sudden application latency) that start with scope or measurement before naming tools.
- Prepare short, concrete answers on code quality, object-oriented versus functional programming, and your Git workflow.
- Prepare a challenging-technical-problem story and a performance-refactor story with before-and-after measurements.
Where candidates lose points
Answering the programming-languages question with a list of everything you have touched
Pick one or two languages from the stack the role lists (Java, C# or Python), say what you built with each, and name one decision you made. Then be ready to code in the language you named.
Writing linked-list reversal or binary search that fails on an empty list, a single node, or an off-by-one midpoint
After writing the code, trace it on empty, one-element and two-element inputs. For binary search, state your loop invariant and use mid = lo + (hi - lo) / 2.
Answering the millions-of-transactions design question by naming microservices, queues and caches immediately
Start with scope and numbers: who calls it, read-versus-write mix, and what must never be lost. Begin with a simple design, find the first bottleneck, and then scale that component.
Treating the latency-spike and hard-bug questions as lists of guesses
Answer in sequence: confirm the symptom in metrics, check what changed and when, find which layer is slow (client, API, database, a dependency), then fix and add monitoring.
Telling behavioral stories in 'we' with no result
For each story, write one sentence about what you personally decided or did, and end with a measured outcome. Rehearse out loud so the story fits in a short answer.
Questions & practice
Write a function to reverse a linked list.
Medium · Coding / Algorithms
Approach
- Use the iterative three-pointer approach: prev = null, curr = head; in a loop save next = curr.next, set curr.next = prev, then advance prev = curr and curr = next; return prev as the new head. O(n) time, O(1) extra space.
- Offer the recursive version as an alternative: reverse the rest of the list, then set head.next.next = head and head.next = null. It is also O(n) time but uses O(n) call stack, so a long list can overflow the stack (Python's default recursion limit is 1,000).
- Walk the edge cases aloud: empty list (return null), a single node, and two nodes; trace the pointers on a three-node list to show no node is lost.
- For a doubly linked list, swap each node's next and prev pointers and return the last node visited.
- Test by building a list, reversing it, and comparing the values read out with the reversed input.
Follow-up
- Reverse only the nodes between positions m and n.
- Reverse the list in groups of k nodes.
- How would you check the list has no cycle before reversing it?
How would you find the shortest path in a graph?
Medium · Coding / Algorithms
Approach
- Clarify the graph first: directed or undirected, weighted or not, can weights be negative, how large is it, and is the question single-source, single pair or all pairs.
- Unweighted graph: breadth-first search from the source, O(V + E), because BFS reaches each node first along a path with the fewest edges. With weights of only 0 and 1, use 0-1 BFS with a deque.
- Non-negative weights: Dijkstra with a binary-heap priority queue, O((V + E) log V); push (distance, node) pairs and skip entries that are stale when popped. On a map or grid with a good admissible heuristic, A* explores fewer nodes.
- Negative weights: Bellman-Ford, O(V x E), which relaxes all edges V - 1 times and reports a negative cycle if a further pass still improves a distance. All pairs on a small dense graph: Floyd-Warshall, O(V^3).
- Return the path, not just the distance, by storing each node's parent and walking back from the target; handle unreachable nodes (distance stays infinite) and ties.
Follow-up
- Why does Dijkstra give wrong answers when some edge weights are negative?
- The graph is a grid with blocked cells. What changes in your code?
- How would you find the shortest path that passes through a given intermediate node?
Explain a sorting algorithm and its time complexity.
Medium · Coding / Algorithms
Approach
- Pick one algorithm and explain it end to end. Merge sort: split in half, sort each half recursively, merge the two sorted halves; O(n log n) in every case, O(n) extra space for arrays, and stable.
- Contrast quicksort: partition around a pivot and recurse; O(n log n) on average but O(n^2) worst case when pivots are poor (for example already sorted input with the first element as pivot); in-place and not stable. A random or median-of-three pivot makes the worst case unlikely.
- Mention the others by their deciding property: heapsort is O(n log n) worst case with O(1) extra space but not stable; insertion sort is O(n^2) in general but close to O(n) on nearly sorted data and fast for small arrays.
- State the limit: comparison sorts need Omega(n log n) comparisons in the worst case; counting sort and radix sort beat it, O(n + k), only for integer keys in a bounded range.
- Connect to the standard libraries: Python's sorted uses Timsort (stable); Java's Arrays.sort uses dual-pivot quicksort for primitive arrays and a stable TimSort for objects; .NET's Array.Sort uses introsort, which is not stable.
Follow-up
- Why does stability matter when you sort records by a second key?
- How would you sort a file too large to fit in memory?
- Write the merge step and walk through it on a small example.
Implement a binary search algorithm.
Medium · Coding / Algorithms
Approach
- State the precondition (the array is sorted) and write the iterative version: lo = 0, hi = n - 1; while lo <= hi, mid = lo + (hi - lo) / 2; return mid on a match, otherwise move lo = mid + 1 or hi = mid - 1; return -1 when the loop ends. O(log n) time, O(1) space.
- Explain the mid calculation: lo + (hi - lo) / 2 avoids integer overflow that (lo + hi) / 2 can cause with 32-bit ints in Java or C#.
- Know the boundary variant: lower bound (first index with a[i] >= target) uses a half-open range, while lo < hi, and sets hi = mid when a[mid] >= target, else lo = mid + 1. Pick one loop invariant and stick to it to avoid off-by-one errors and infinite loops.
- Test the edge cases: empty array, one element, target below the minimum or above the maximum, and duplicates.
- Mention the library versions: Python's bisect.bisect_left; Java's Arrays.binarySearch returns -(insertion point) - 1 when the key is absent; .NET's Array.BinarySearch returns the bitwise complement of the insertion index.
Follow-up
- Find the first and last positions of a target in a sorted array with duplicates.
- Search for a target in a sorted array that has been rotated.
- Use binary search on the answer: find the minimum capacity that ships all packages within D days.
Discuss the trade-offs between different data structures.
Medium · Coding / Algorithms
Approach
- Organise the answer around operations and their costs. Dynamic array: O(1) access by index, amortised O(1) append, O(n) insert or delete in the middle, and good cache locality. Linked list: O(1) insert or delete once you hold the node, but O(n) to find it and poor locality.
- Hash map: average O(1) insert and lookup, but no ordering, extra memory, and a worse worst case under heavy collisions (Java 8+ HashMap turns large collided buckets into trees to cap that). Balanced search tree (Java TreeMap, C# SortedDictionary): O(log n) operations plus ordered iteration and range queries.
- Heap or priority queue (Python heapq, Java PriorityQueue): O(1) to read the minimum, O(log n) to push or pop; the right choice for top-k, scheduling and Dijkstra. Stacks, queues and deques give O(1) at their ends.
- Choose from the access pattern with a concrete example: looking up stock by item code is a hash map; querying orders in a date range needs an ordered structure, which in a SQL database is a B-tree index.
- Mention memory and constant factors: for small n a sorted array with binary search can beat a hash map, and a trie suits prefix search such as autocomplete.
Follow-up
- Design an LRU cache with O(1) get and put. Which structures do you combine?
- When would a sorted array beat a hash map?
- What happens to hash map performance as the load factor grows, and what does resizing cost?
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
- 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.
- 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.
- 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.
- 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?
Stop tag and share joins from fanning out a page
Medium · join fan-out · semi-joins · many-to-many
resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.
Approach
- Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
- Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
- Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
- Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.
Follow-up
- The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
- A resource can be shared with the same user twice under different permissions. Does your count change, and should it?
What programming languages are you most comfortable with and why?
Medium · Technical / Domain Questions
Approach
- Name one primary language and show real depth in it: its runtime model (JVM or .NET CLR garbage collection, or the CPython interpreter and its GIL), its build and dependency tooling (Maven/Gradle, dotnet CLI, pip/Poetry), and its test framework (JUnit, xUnit/NUnit, pytest).
- Anchor the answer in the languages candidates list for this role (Java, C#, Python): say which ones you have shipped production code in, and for what kind of system.
- Give the 'why' as a trade-off, not a preference: static typing in Java and C# catches type errors at compile time and makes large refactors safer; Python is faster to write and iterate on, but in standard CPython builds the GIL lets only one thread run Python bytecode at a time, so CPU-bound work needs multiprocessing or native code.
- Back it with one concrete feature you relied on, for example async/await and LINQ in C#, streams and records in Java, or dataclasses plus type hints checked by mypy in Python.
- Be explicit about a weaker language and how you would ramp up on it, rather than claiming equal fluency in everything.
Follow-up
- How does garbage collection work in your main language, and have you ever had to tune it or debug a memory leak?
- For a new back-end service, when would you pick Python over Java or C#, and when not?
- Which feature of your main language do you avoid in production code, and why?
Describe a challenging technical problem you faced and how you resolved it.
Medium · Technical / Domain Questions
Approach
- Choose a problem with a technical root cause you personally found, not a schedule crunch: a race condition, a slow query, a memory leak, a data corruption bug, an integration failure.
- Structure it as symptom, constraints, hypotheses tested and ruled out, root cause, fix. The ruled-out hypotheses show method; a story that jumps straight to the answer shows luck.
- Quantify the before and after (p99 latency, error rate, job runtime, failed orders per day) and say how you measured it.
- Close with what you changed so it cannot recur: a regression test, an alert, a lint rule, a runbook entry or a design change.
- Keep 'I' and 'the team' distinct so it is clear which decisions were yours.
Follow-up
- Which alternative fixes did you reject, and why?
- How did you confirm the fix worked in production and not just on your machine?
- Looking back, what signal could have caught this problem earlier?
How do you ensure code quality and maintainability?
Medium · Technical / Domain Questions
Approach
- Start with automated gates in CI so quality does not depend on memory: a formatter and linter (Black/Ruff, Checkstyle/SpotBugs, dotnet format/Roslyn analyzers, ESLint for React or Angular code), static analysis, and tests that must pass before merge.
- Describe a test strategy by layer: fast unit tests for logic, integration tests against a real database (for example in a container) for SQL and repository code, and contract tests for REST APIs so a provider change cannot silently break a consumer.
- Explain design habits that keep code changeable: small functions with one responsibility, clear module boundaries, dependency injection so collaborators can be faked in tests, and names that make comments about 'what' unnecessary.
- Cover review practice in Git: small pull requests, a description of why the change exists, reviewers focused on correctness and design while tools handle style.
- Treat metrics as signals, not targets: coverage shows untested code but high coverage does not prove good tests; defect escape rate and change failure rate say more.
Follow-up
- How do you make a change safely in legacy code that has no tests?
- What coverage target would you set for a team, and what problems can a hard target cause?
- How do you handle a code review where you and the reviewer disagree on design?
Can you explain the differences between object-oriented and functional programming?
Medium · Technical / Domain Questions
Approach
- Define both precisely. Object-oriented programming groups state and the behaviour that acts on it into objects, using encapsulation, inheritance and polymorphism through dynamic dispatch. Functional programming builds programs from pure functions over immutable values, treats functions as first-class values and composes them (map, filter, reduce).
- Give the core trade-off (the expression problem): with classes, adding a new type is easy (a new subclass) but adding a new operation touches every class; with algebraic data types and pattern matching, adding an operation is easy but adding a new variant touches every function.
- Explain the practical benefit of purity and immutability: the same input always gives the same output, so tests need no setup or mocks, and shared immutable data removes a whole class of concurrency bugs.
- Note that Java, C# and Python mix both styles: Java lambdas, streams and records; C# LINQ, records and pattern matching; Python comprehensions, functools and frozen dataclasses.
- Show a small example: an order total computed by a pure function over immutable line items versus an Order class whose mutable state is updated in place, and say when each is clearer.
Follow-up
- What makes a function pure, and why is it easier to test?
- When does inheritance cause trouble, and what would you use instead?
- How would you model an immutable domain object in Java or C#?
How would you design a system to handle millions of transactions per second?
Medium · System Design / Architecture
Approach
- Clarify before drawing anything: what a transaction is (a payment, a stock decrement, an event write), the read/write ratio, peak versus average load, the latency target and whether every transaction needs strong consistency.
- Do the arithmetic aloud: 1 million writes per second at about 1 KB each is about 1 GB/s of ingest, roughly 86 TB per day, which rules out a single database node and forces partitioning plus a retention plan.
- Outline the architecture: stateless API servers behind load balancers that scale horizontally; data sharded by a key such as account or item id; a partitioned append-only log (Kafka-style) to absorb writes, with consumers updating stores asynchronously.
- Handle correctness per key: route every write for a key to one partition so updates to it are serialised without a distributed lock; require idempotency keys so client retries are not applied twice; for operations that span keys, use a saga with compensating steps rather than two-phase commit on the hot path.
- Name the failure modes and their fixes: hot keys (split or shard the key further), replication lag, backpressure and rate limiting when consumers fall behind, and replication across availability zones.
Follow-up
- One item suddenly gets a large share of all traffic. What breaks and how do you fix it?
- How do you guarantee a transaction is applied exactly once when the client times out and retries?
- How would you add shards later without downtime?
What considerations do you make for system scalability and reliability?
Medium · System Design / Architecture
Approach
- Split the answer into scalability and reliability. For scale: stateless services so instances can be added freely, caching (cache-aside with TTLs and a clear invalidation rule), read replicas, partitioning, and queues to smooth bursts. Find the real bottleneck with a load test before adding any of these.
- For reliability: redundancy across availability zones, health checks, timeouts on every remote call, retries with exponential backoff and jitter, circuit breakers, and idempotent operations so retries are safe.
- Define the targets first: SLIs such as p99 latency and error rate, an SLO for each, and an error budget that decides when to stop shipping features and fix stability.
- Cover observability (metrics, structured logs, distributed traces) and data safety: backups with restores actually tested, and an RPO (how much data you can lose) and RTO (how long you can be down) agreed per system.
- Mention graceful degradation: serve cached or partial results when a dependency is down rather than failing the whole page.
Follow-up
- Retries can make an outage worse. How do you prevent a retry storm?
- How would SLOs differ for an internal inventory tool and a customer-facing website?
- What is the difference between RPO and RTO, and how does each change your backup design?
Describe how you would approach designing a microservices architecture.
Medium · System Design / Architecture
Approach
- Start from domain boundaries, not technology: identify bounded contexts (for example orders, inventory, customers, billing), give each service sole ownership of its data, and forbid other services from reading its database directly.
- Say when not to split yet: a modular monolith is often the right first step, and services earn their cost when teams need independent deploys or parts of the system scale differently.
- Choose communication per interaction: synchronous REST or gRPC when the caller needs an answer now, asynchronous events through a broker for decoupling. Avoid long synchronous chains, because availabilities multiply: five services at 99.9% each give about 99.5% end to end.
- Handle cross-service consistency with sagas and compensating actions, and publish events with a transactional outbox so a database write and its event cannot diverge.
- List the platform pieces: API gateway, service discovery, centralised configuration, distributed tracing with correlation ids, a CI/CD pipeline per service, versioned APIs and consumer contract tests.
Follow-up
- How would you break an existing monolith into services without a big-bang rewrite?
- An operation must update data owned by two services. How do you keep them consistent?
- When would you argue against microservices for a project?
How would you approach solving a sudden increase in application latency?
Medium · Problem-Solving / Case Studies
Approach
- Scope the symptom first: which endpoints, all users or one region, p50 or only p99, and exactly when it started. Then line that time up against deploys, config changes, traffic spikes and dependency incidents.
- Read the dashboards in a fixed order: request rate, errors and duration per service, then utilisation and saturation on hosts (CPU, memory, connection pools, thread pools, disk I/O). Use distributed traces to find which span grew.
- Check the usual causes: a slow database query (missing index, changed query plan, lock contention; confirm with the slow-query log and EXPLAIN ANALYZE), connection pool exhaustion, garbage collection pauses, a slower downstream service, or a drop in cache hit rate.
- Mitigate before finding the root cause: roll back a suspect deploy, scale out, or shed non-essential load, then investigate with the pressure off.
- Finish with prevention: an alert on the latency SLO, a regression test or query review, and a short written postmortem.
Follow-up
- p50 is flat but p99 has tripled. What does that suggest?
- Latency rose with no deploy and no traffic change. Where do you look next?
- How would you confirm a missing index is the cause before adding one in production?
What steps would you take to improve user experience for a web application?
Medium · Problem-Solving / Case Studies
Approach
- Measure before changing anything: real-user monitoring and Core Web Vitals (LCP for loading, INP for responsiveness, CLS for layout stability; the 'good' thresholds are 2.5 s, 200 ms and 0.1), funnel analytics showing where users drop off, and support tickets or session feedback.
- Fix performance where the data points: code splitting and lazy loading in React or Angular, correctly sized and compressed images, CDN caching for static assets, less render-blocking JavaScript, and lighter API responses (pagination, no over-fetching).
- Fix usability and accessibility: semantic HTML, keyboard navigation, labelled form fields, sufficient colour contrast (WCAG), clear loading and error states, and validation messages that say how to fix the input.
- Prioritise by impact on users and effort, and ship changes behind feature flags so they can be compared with the old version through an A/B test or a staged rollout.
- Confirm the result against the metric you started from, and watch that one fix does not hurt another (for example lazy loading that worsens LCP for above-the-fold images).
Follow-up
- What does each Core Web Vital measure, and what usually makes INP poor?
- You have ten UX complaints and time to fix two. How do you choose?
- How would you show a change improved the experience and did not just move one metric?
How would you design a feature based on user feedback?
Medium · Problem-Solving / Case Studies
Approach
- Turn raw feedback into a problem statement: group tickets, survey answers and interviews, look for the underlying need rather than the literal request, and check how many users and how often with analytics.
- Agree on scope and a success metric with the product manager before building: the smallest version that tests the idea, written acceptance criteria, and what number should move.
- Outline the technical design: data model and migration, a backward-compatible REST API contract, front-end changes, and how existing clients keep working during rollout.
- Ship behind a feature flag to a small group first, instrument the events that feed the success metric, and compare against a baseline or control group.
- Plan for conflicting feedback across user segments, and decide in advance what result would make you iterate, expand or remove the feature.
Follow-up
- Two groups of users ask for opposite behaviour. How do you decide what to build?
- How would you roll this feature out safely, and how would you roll it back?
- Which metric would tell you the feature failed?
Explain how you would handle a project with unclear requirements.
Medium · Problem-Solving / Case Studies
Approach
- List what is known, what is assumed and what is unknown, then take targeted questions to the people who own the answers: users, the product manager, the teams whose systems are affected.
- Write a short one-page spec stating the goal, the assumptions, what is out of scope and the open questions, and get the stakeholders to confirm it before major build work.
- Build the smallest end-to-end slice or a prototype early, because showing something working usually surfaces the missing requirements faster than meetings do.
- Design for change where uncertainty is highest: keep the uncertain parts behind interfaces or configuration so a changed requirement means a local change, not a rewrite.
- Keep risks visible: say which decisions are reversible, timebox the exploration, and report changed assumptions as soon as they change.
Follow-up
- A stakeholder changes a key requirement halfway through. What do you do?
- How do you decide you know enough to start building?
- Tell me about an assumption that turned out to be wrong. What did it cost?
Describe your thought process when debugging a difficult issue.
Medium · Problem-Solving / Case Studies
Approach
- Reproduce it first: capture the inputs, environment and versions, and shrink it to the smallest failing case. If it cannot be reproduced, add logging or tracing around the suspect path and wait for the next occurrence.
- Read the actual error and stack trace, then list hypotheses and test the cheapest, most discriminating one first. Each test should rule something out whichever way it turns out.
- Bisect: git bisect over commits between a known-good and known-bad version (about 10 steps for 1,000 commits, since log2 of 1,000 is just under 10), or halve the input data or configuration until the trigger is isolated.
- Compare a working and a failing environment (library versions, config, data, time zone, feature flags). For intermittent bugs, suspect races, timeouts, caching and clock issues, and try to make the timing deterministic.
- Fix the root cause, not the symptom, and add a regression test that fails before the fix and passes after.
Follow-up
- How would you debug something that only happens in production and cannot be reproduced locally?
- How do you tell a real cause from a coincidence in the logs?
- When do you stop debugging alone and ask someone for help?
Suggested practice checklist
The plan starts with the two reported stages and the stack, then works through the reported coding, engineering-practice, design, debugging and behavioral questions, ending with a full spoken run-through.
Day 1 — Map the loop and settle your language and stack story
- Write the two reported stages and what each needs from you, then list the stack the role names (Java, C# or Python; React or Angular; Git; SQL and NoSQL; REST APIs; AWS or Azure; CI/CD) and mark what you have shipped with.
- Choose the language you will code in and write your answer to the languages question around one real project.
- Write a short CV walkthrough that names the language, framework and database on each project.
Deliverable: A one-page loop map with your stack inventory, a written languages answer and a written CV walkthrough.
Day 2 — Core coding problems by hand
- Write reverse a linked list both iteratively and recursively, and trace each on empty, one-node and two-node lists.
- Write binary search (plus the variant that returns the first match among duplicates) and check the midpoint arithmetic.
- Write one comparison sort and one linear-time-friendly alternative, and state best, average and worst time, space and stability for each.
Deliverable: Three working solutions in your chosen language, each with a written edge-case trace and a complexity line.
Day 3 — Graphs and data-structure trade-offs
- Solve shortest path twice: BFS on an unweighted graph, then Dijkstra with a heap on non-negative weights; note why negative edges need Bellman-Ford.
- Write one table comparing array, linked list, hash map, balanced tree, heap, stack and queue by lookup, insert, delete and ordering.
- Pick three everyday tasks from an inventory or customer application and name the data structure you would use for each.
Deliverable: Working BFS and Dijkstra code, a one-page data-structure comparison table, and three written task-to-structure choices.
Day 4 — Engineering practice and debugging answers
- Write and say aloud your answers on code quality, object-oriented versus functional programming (with one code example of each style) and your Git workflow.
- Write a debugging sequence you can follow for any hard bug, then a latency-spike checklist ordered by layer.
- Note one real bug from your career and match it to the sequence.
Deliverable: Four spoken answers (code quality, OO versus functional, Git workflow, debugging process) plus a written latency checklist.
Day 5 — System design and consistency
- Sketch a design for millions of transactions per second: requirements, partition key, write path, read path, queues and failure behaviour.
- Write a scalability-and-reliability checklist: redundancy, timeouts, retries with backoff, rate limiting, health checks, graceful degradation and monitoring.
- Outline how you would split an application into microservices, where you would not, and how data consistency across the services is kept (saga, outbox, idempotency).
Deliverable: One annotated design diagram, one reliability checklist and one microservices-and-consistency outline.
Day 6 — Case-style problems, SQL and the technical-problem story
- Answer the web-UX, user-feedback feature and unclear-requirements questions aloud, each with a first step, a measure of success and a trade-off.
- Write your challenging-technical-problem story and your performance-refactor story with before-and-after numbers.
Deliverable: Three spoken case answers, two written stories with measurements, and two solved SQL practice queries.
Day 7 — Behavioral run-through and full rehearsal
- Write a story for each behavioral question (difficult team member, feedback, deadlines, leading an initiative, adapting to change), each naming your role and the result.
- Say all five aloud, then record yourself and cut any answer that runs long or hides your own part in 'we'.
- Rehearse the screening conversation end to end, then do one last timed pass of the linked-list, binary-search and design answers.
Deliverable: Five written and recorded behavioral stories, plus a final checklist of the answers that still need work.
Behavioral stories to rehearse
The reported behavioral questions cluster around working with people (a difficult colleague, feedback, adapting to change) and managing work (deadlines, owning an initiative, refactoring for performance). The responsibilities candidates describe include agreeing scope with product managers, code review, and cross-department projects, so draw stories from those settings and name your personal role and the measured result in each.
What is your experience with version control systems?
Medium · Technical / Domain Questions
Approach
- Describe your actual workflow instead of saying you use Git: how branches are cut (short-lived feature branches off main, or trunk-based), how changes reach review (pull requests), and what must pass before merge (tests, linters, a required review). The requirements candidates describe list Git, so this should be a fluent answer.
- Know when you choose each integration method. Rebase keeps a feature branch linear before review, merge preserves history on shared branches, and squash condenses noisy commits. State the rule that you never rebase commits other people have already pulled.
- Bring recovery skills: git revert to undo a commit that is already on main, reset for local mistakes, reflog to find commits that seem lost, cherry-pick to move a fix onto a release branch, and bisect to find the commit that introduced a bug.
- Close with one concrete story: a merge conflict or bad merge you fixed, what you did, and what you changed afterwards (smaller pull requests, protected main, commit message conventions). A tool list with no story is the weak version of this answer.
Follow-up
- Someone pushed a broken commit to main and others have already pulled it. How do you undo it?
- When would you choose merge over rebase on a shared branch?
- How do you find which commit introduced a regression?
How do you handle data consistency across distributed systems?
Medium · System Design / Architecture
Approach
- Start by classifying the data. A stock count or an order total that must never be wrong needs strong consistency, while a product listing or a dashboard can be seconds stale. Say which one you are designing for before naming a technique.
- Keep related writes inside one database transaction for as long as you can. Choose the isolation level deliberately and prevent lost updates with row locks (SELECT ... FOR UPDATE) or an optimistic version column that makes a stale write fail.
- When one business operation spans services, avoid two-phase commit across them. Use a saga: each step has a compensating action (release the reservation, refund the payment), run by an orchestrator or a chain of events, so a failure rolls the operation back.
- To update a database and publish an event atomically, use the transactional outbox: write the event row in the same transaction and let a relay publish it. Delivery is at-least-once, so consumers need an idempotency key or a processed-message table to ignore duplicates.
- Name the trade-off. Replicas lag, so a read that must see a just-made write goes to the primary. Add a reconciliation job that compares the sources of truth and repairs drift, and say how you would alert on it.
Follow-up
- Payment succeeded but the inventory reservation failed. What happens next?
- Why is exactly-once delivery hard, and how does idempotency substitute for it?
- How would you detect that two services have drifted out of agreement?
Discuss a time when you had to refactor a system for better performance.
Medium · System Design / Architecture
Approach
- Open with the situation in one or two sentences: what was slow, who felt it, and the number (page load time, query time, job duration). A performance story without a baseline measurement is the common reason this answer fails.
- Show how you found the bottleneck instead of guessing: a profiler, an EXPLAIN plan, tracing, or logs. Name what it revealed (an N+1 query, a missing index, a hot loop, an unbounded payload).
- Describe the refactor and the reason for the shape you chose, and how you kept behaviour safe: characterisation tests before changing code, a feature flag or staged rollout, and a comparison of old and new outputs.
- Finish with the measured result in the same unit as the baseline, the trade-off you accepted (more memory, a cache to invalidate, added complexity), and what you would monitor afterwards.
Follow-up
- How did you know that part of the system was the bottleneck?
- How did you make sure the refactor did not change behaviour?
- What did the faster version cost you in complexity or maintenance?
Describe a time you had to work with a difficult team member. How did you handle it?
Medium · Behavioral / Leadership
Approach
- Choose a real conflict about work (a review dispute, missed handoffs, a dismissive colleague) and describe behaviours and effects on the project, not a character verdict. A story that mostly vents about the person sinks this answer.
- Show that you tried a direct, private conversation first: you asked what constraints or goals the other person had, and you shared the specific impact on the work.
- Describe what you changed on your side and what you agreed on together, for example a working agreement, clearer ownership, or moving a disagreement to a short design discussion with data.
- State when you would involve a manager and how, then give the outcome: a shipped result, a repaired working relationship, or an honest note about what remained unresolved.
Follow-up
- What would you have done if the behaviour had not changed?
- When is it right to escalate to a manager?
- What did the situation teach you about your own working style?
What is your approach to receiving and giving constructive feedback?
Medium · Behavioral / Leadership
Approach
- Cover both directions with one example each. For receiving, pick specific review feedback that first stung or that you disagreed with, say how you checked whether it was right (tested it, asked for an example), and what you changed.
- For giving, describe how you write code review comments: specific, about the code instead of the person, with the reason and a suggested alternative, and a clear distinction between blocking issues and minor nits. Sensitive feedback goes in a conversation, not a thread.
- Mention follow-through: you check that feedback landed, and you ask others for feedback on your own reviews and design documents.
- Avoid generic claims such as 'I welcome feedback'. The answer works only when there is an outcome, such as a pattern you stopped using or a teammate who changed how they structured pull requests.
Follow-up
- Tell me about feedback you disagreed with. What did you do?
- How do you give feedback to someone more senior than you?
- How do you handle a teammate who reacts badly to review comments?
How do you prioritize your work when faced with multiple deadlines?
Medium · Behavioral / Leadership
Approach
- Describe a method that you really use: list every commitment, note who depends on each one and what slips if it is late, and rank by impact and fixed dates rather than by who asked loudest.
- Show negotiation instead of overwork. Say how you took the conflict to the product manager or stakeholders, offered options (cut scope, move a date, add help), and got an explicit decision.
- Give a real example with specifics: two deadlines in the same week, what you chose to do first, what you deferred, and how you told the affected people.
- Say what you do when a deadline will be missed: raise it early with the reason and a new estimate. 'I just work harder' is the answer to avoid.
Follow-up
- What if two stakeholders each insist their deadline is the priority?
- Tell me about a deadline you missed and what you did.
- How do you estimate so that deadlines clash less often?
Share an example of how you’ve led a project or initiative.
Medium · Behavioral / Leadership
Approach
- Pick an initiative where you owned the outcome, even without a manager title: a migration, a new service, a testing effort, a release. Say what the goal was and why it needed an owner.
- Make your own role explicit. Describe how you broke the work into pieces, who took which part, how you aligned product managers and other engineers on scope, and how you kept the plan visible. Saying 'we' for every step hides what you did.
- Include one problem that appeared mid-way (a dependency slipped, a design assumption failed) and the decision you made about it.
- Close with the result in measurable terms, what you would do differently, and how you helped others on the team grow or gain context during the work.
Follow-up
- How did you divide the work, and how did you track progress?
- What went wrong, and how did you adjust?
- How did you measure whether the initiative succeeded?
How do you adapt to change within a team or project?
Medium · Behavioral / Leadership
Approach
- Choose a real change: requirements shifting mid-sprint, a reorganised team, a new framework or tool, a cancelled project. Describe the change and your first reaction honestly.
- Show the steps you took: ask why the change happened, work out what it did to the plan, tell the people affected the new timeline, and salvage what you could from work already done.
- Show learning, such as picking up an unfamiliar tool by building a small prototype or pairing with someone who knew it, and the adjustment you made to tests, docs and handoffs.
- Give the outcome, and mention a change you questioned: you raised the concern with evidence and then committed to the decision. Someone who only complies or only resists has not answered the question.
Follow-up
- Tell me about a change you disagreed with. What did you do?
- How do you handle a requirement that changes in the middle of a sprint?
- How do you reduce churn when priorities keep moving?