cswork / libraryOpen practice workspace

Interview guides · Boxed

Boxed Software Engineer Interview Guide

Boxed Software Engineer interview guide: five reported rounds, coding and system design questions, behavioral prompts and a 7-day preparation plan.

The 60-second brief

Boxed is described to candidates as an e-commerce company, and the Software Engineer role sits on the engineering team that builds and maintains the technology behind that platform. Candidates report responsibilities that include designing and building software, writing and reviewing code, tracking down performance bottlenecks in existing systems, testing and deploying releases, and taking part in agile ceremonies. The work is described as collaborative, with product managers and designers helping shape the features engineers deliver. The requirements candidates describe name Python, Java or JavaScript, cloud platforms such as AWS or Azure, and Git, with containers, SQL and NoSQL databases and front-end frameworks as extras.

This guide is for candidates preparing for a Software Engineer interview at Boxed. It covers the five rounds candidates report, the reported question set (technical background, coding, behavioral, production debugging and feature case studies, and system design), a seven-day plan that moves from algorithms to design to stories, and the mistakes that cost points on these question types.

Candidates report five rounds over roughly 4-6 weeks: a Phone Screen, a Coding Assessment, a Hiring Manager Interview, an Onsite Interview and a Call with Senior Leadership.

Focus areas

  • Coding Assessment
  • Time-Bound Problem Solving
  • Preparation for Coding Interviews

Overview

The reported work for this role is ordinary product engineering: building features with product managers and designers, reviewing code, running through agile ceremonies, testing and deploying, and finding performance bottlenecks in systems that already exist. That shapes what to rehearse. Be ready to talk about shipping and maintaining software, not only solving puzzles, and keep a few real examples of review feedback, a release you owned and a slow path you sped up.

The questions candidates report fall into five groups. Technical background covers object-oriented programming, version control, REST versus SOAP, cloud experience and a hard problem you solved. Coding covers reversing a linked list, binary search, finding two numbers that add up to a target, explaining complexity and a dynamic programming problem. Behavioral covers pressure, prioritising, conflict, motivation and communication. Case studies cover debugging a production issue, designing a feature for the Boxed platform, prioritising with limited resources, measuring a feature and scope creep. System design covers a URL shortener, a system for millions of users, microservices versus a monolith, consistency in distributed systems and database performance. Because the reports do not tie each question to one round, prepare all five groups rather than guessing.

On the stack, the requirements candidates describe list Python, Java or JavaScript, so choose the one you write most fluently and do every coding exercise in it. Cloud platforms (AWS or Azure) and Git are listed as must-haves, which means the cloud and version control questions deserve real stories with specifics rather than a tool list. Docker, Kubernetes, SQL and NoSQL databases, React and Angular are listed as nice to have; the plan includes SQL practice drills for that reason, and the database performance question is a natural place to show it.

The loop is reported at five rounds over about 4-6 weeks, ending with a call with senior leadership that candidates describe as centered on transparency and communication. With that many conversations, the same projects will come up more than once. Settle your two or three main project stories early, including what went wrong, so that your account stays consistent from the recruiter call through the final call.

The Boxed interview process

Candidates describe five rounds across roughly 4-6 weeks. The names and one-line summaries below are what candidates report; they do not say which question types fall in which round, so each round lists preparation by type.

Phone Screen

Candidates describe an opening call with a recruiter that looks at your background and how well you fit the role. Treat it as the place where your CV, your language and cloud experience and your logistics get matched against the requirements candidates describe for this role: Python, Java or JavaScript, a cloud platform such as AWS or Azure, and Git.

What to demonstrate

  • Background and role fit, which is how the call is described
  • How your languages and cloud experience line up with the listed requirements
  • How concisely you can summarise your recent engineering work

How to prepare

  • Write a short walkthrough of your last two roles that names the language, the cloud platform and the Git workflow you used in each.
  • Prepare a specific reason for applying to an e-commerce engineering team, tied to work you have done rather than to the company's description of itself.
  • Know your availability, location constraints and compensation expectations, and ask the recruiter to confirm the remaining rounds and their order.

Coding Assessment

This stage is reported as an assessment of technical skills through coding. Candidates describe live coding or take-home assessments in general, and the reported coding questions cover reversing a linked list, binary search, two numbers that add up to a target, explaining complexity and a dynamic programming problem. Practise writing complete, tested code in one language rather than sketching ideas.

What to demonstrate

  • Working code in the language you choose
  • Fundamentals: linked lists, searching, hashing and dynamic programming
  • Stating time and space complexity and the trade-off behind your choice

How to prepare

  • Pick Python, Java or JavaScript and write linked list reversal, binary search and two-sum from a blank file with no autocomplete.
  • For each solution, say the brute-force version, the improved version and the complexity of both, then run tests for empty input, a single element and duplicates.
  • Solve one dynamic programming problem top-down with memoisation and bottom-up, and write the state definition and recurrence in a comment before coding.
  • If you receive a take-home, add tests and a short README on how to run it and what the complexity is.

Hiring Manager Interview

Candidates describe an in-depth conversation with the hiring manager about your experience and fit with the team. This is where the version control, cloud experience, hard-problem and prioritisation questions are practised, because they are about work you have already done. Come with concrete projects where you owned a decision.

What to demonstrate

  • Depth of your past engineering experience
  • Fit with a team that works with product managers, designers and other engineers
  • How you describe decisions, trade-offs and outcomes in your own projects

How to prepare

  • Prepare two projects in detail: the problem, your part, a design decision with its alternatives, the result and what you would change.
  • Write specific answers for how you used Git with a team and what you ran on a cloud platform, naming services and practices.
  • Prepare questions about the team's roadmap, code review habits and how the team handles releases and performance work.

Onsite Interview

The onsite is reported as a series of interviews that assess skills and fit further. Candidates do not say which question types land in which conversation, so cover the whole reported set: coding, system design (URL shortener, millions of users, microservices versus monolith, consistency, database performance), production debugging, feature design and behavioral prompts.

What to demonstrate

  • Technical skills across coding and design, as a series of interviews implies
  • Fit with the team, which the stage is described as examining
  • Ability to switch between hands-on code and architectural discussion

How to prepare

  • Do a full URL shortener design aloud: requirements, ID generation, storage, the redirect read path, caching and what happens at ten times the traffic.
  • Prepare a one-page comparison of microservices and a monolith with a concrete example of when you would pick each.
  • Write a production-debugging routine you can recite: check recent changes and deploys, confirm the symptom in logs and metrics, narrow by bisection, mitigate or roll back, then find the root cause.
  • Rehearse one coding problem and one behavioral story back to back to practise switching modes.

Call with Senior Leadership

The last step is a call with senior leadership, which candidates describe as an exchange emphasizing transparency and communication. Prepare to explain your work and decisions plainly to someone outside your day-to-day team, including what did not go well.

What to demonstrate

  • Transparency and communication, the emphasis candidates report for this call
  • How clearly you explain your work and its results to a senior audience

How to prepare

  • Write a two-minute account of your best project that a non-specialist can follow, with the outcome stated up front.
  • Prepare an honest example of a mistake or missed date, what you told people and when, and what changed afterward.
  • Write a few questions about engineering priorities and how the team measures the success of a new feature.

Where candidates lose points

Solving two-sum with nested loops and stopping, or giving the hash map answer without saying why it is faster

State the brute-force O(n^2) version, then the one-pass hash map in O(n) time and space, and test duplicates, negatives and using the same element twice.

Writing binary search with off-by-one errors or a loop that never ends, then debugging live

Define the search range invariant before coding, compute the midpoint safely, move bounds past mid, and trace an empty list, one element and an absent target.

Reversing a linked list by overwriting the next pointer before saving it, losing the rest of the list

Keep previous, current and next references, relink in that order, and test the empty list and a single node. Be ready to write the recursive version and say it uses O(n) stack.

Answering the URL shortener or millions-of-users question with component names and no numbers or trade-offs

Ask for read and write volume, link lifetime and latency goals first, then justify ID generation, storage and caching against them, and say where you accept stale or eventually consistent data.

Telling behavioral stories in terms of what the team did, so no decision of yours appears

For each prompt, name the decision you personally made, the alternative you rejected, the result and what you would change. Prepare a separate story per prompt to avoid reusing one.

Questions & practice

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Clarify the node shape (singly linked, val and next) and that the function returns the new head; state the edge cases up front: empty list, one node, two nodes.
  2. Iterative solution with three pointers: prev = None, curr = head; in the loop save nxt = curr.next, set curr.next = prev, then advance prev = curr and curr = nxt; return prev. O(n) time, O(1) extra space.
  3. Mention the recursive version (reverse the rest, then set head.next.next = head and head.next = None) and its cost: O(n) call-stack space, which can hit Python's default recursion limit of about 1000 on long lists.
  4. Trace it aloud on 1 -> 2 -> 3 to show no node is lost, and point out the classic bug: overwriting curr.next before saving the next node.

Follow-up

  • Reverse only the nodes between positions m and n in one pass.
  • Reverse the list in groups of k, leaving a short final group as it is.
  • Use the reversal to check whether a linked list is a palindrome in O(1) extra space.

How would you implement a binary search algorithm?

Medium · Coding / Algorithms

Approach

  1. State the precondition: the array is sorted (or the predicate is monotonic). Without it binary search is wrong, and sorting first costs O(n log n).
  2. Write the inclusive version: lo = 0, hi = n - 1, loop 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 not found. O(log n) time, O(1) space.
  3. Explain why mid is computed as lo + (hi - lo) / 2: in Java or C with fixed-width ints, (lo + hi) can overflow on large arrays. Python ints do not overflow, but the habit carries across languages.
  4. Handle duplicates with the lower-bound variant: on a half-open range [lo, hi) keep hi = mid when a[mid] >= target, giving the first index not less than the target; this is what Python's bisect_left returns. Java's Arrays.binarySearch returns -(insertion point) - 1 when the key is absent.
  5. Test the edges aloud: empty array, a single element, target smaller than the first or larger than the last element, and a target repeated across the whole array.

Follow-up

  • Find the first and last positions of a target in a sorted array with duplicates.
  • Search a sorted array that has been rotated at an unknown pivot.
  • Use binary search on the answer: the minimum capacity needed to ship all packages within D days.

Given a list of integers, find two numbers that add up to a specific target.

Medium · Coding / Algorithms

Approach

  1. Clarify the contract: return indexes or values, is there exactly one answer, can the same element be used twice, and can values be negative or repeated.
  2. Name the brute force (check every pair, O(n^2) time, O(1) space), then improve it with a hash map from value to index: for each x, check whether target - x is already in the map, and only then insert x. O(n) time, O(n) space.
  3. Explain why checking before inserting matters: it stops an element pairing with itself (target 6, value 3 once) while still finding [3, 3] when 3 appears twice.
  4. Give the alternative when memory is tight or the input is already sorted: two pointers from both ends, moving the left pointer up when the sum is too small and the right one down when it is too large. O(n) on sorted input, O(n log n) if you must sort, and you lose the original indexes unless you sort (value, index) pairs.

Follow-up

  • Return all unique pairs that sum to the target, without duplicates.
  • Extend it to three numbers that sum to zero; what complexity can you reach?
  • How would you solve it if the integers arrive as a stream too large to hold in memory?

Explain the time complexity of your solution and any trade-offs involved.

Medium · Coding / Algorithms

Approach

  1. State time and space separately and say which case you mean: worst, average or amortized. For example, a hash map lookup is O(1) on average but O(n) in the worst case under heavy collisions.
  2. Count all the space you use: auxiliary structures and the recursion stack. A recursive DFS on a skewed tree uses O(n) stack even with no explicit data structure.
  3. Name the trade-off you made explicitly: extra memory for speed (a hash set turns O(n^2) pair checks into O(n)), or preprocessing cost for faster queries (sort once in O(n log n), then answer each lookup with binary search in O(log n)).
  4. Use amortized analysis where it applies: appending to a dynamic array (Python list, Java ArrayList) is amortized O(1) because capacity grows geometrically, even though a single resize is O(n).
  5. Connect the bound to the input size you were given: at n = 10^5 an O(n^2) solution is about 10^10 operations and too slow, while for tiny n a simpler O(n^2) solution may be the clearer choice.

Follow-up

  • Quicksort is O(n log n) on average; what input makes it O(n^2), and how do implementations avoid it?
  • Your solution is O(n) but uses O(n) memory; can you keep the time and bring space down to O(1)?
  • Why is comparison-based sorting bounded below by O(n log n), and how does counting sort get around it?

Can you solve a problem using dynamic programming?

Medium · Coding / Algorithms

Approach

  1. Say how you recognise a DP problem: optimal substructure plus overlapping subproblems, usually phrased as a minimum, maximum, count of ways, or a yes/no over choices.
  2. Define the state, recurrence, base case and evaluation order out loud. For coin change (fewest coins): dp[0] = 0, dp[a] = min over coins c <= a of dp[a - c] + 1, with unreachable amounts kept at infinity and reported as -1. O(amount x coins) time, O(amount) space.
  3. Show why greedy fails so DP is justified: with coins {1, 3, 4} and amount 6, greedy takes 4 + 1 + 1 (three coins) while the optimum is 3 + 3 (two).
  4. Compare top-down memoisation (natural to write, recursion depth risk) with bottom-up tabulation (iterative, easy to shrink); then reduce memory when a row only depends on the previous one, for example two variables for house robber or two rows for longest common subsequence.
  5. Test the edges: amount 0, no coin smaller than the amount, a single coin type, and large amounts where an exponential recursion without memoisation would time out.

Follow-up

  • Reconstruct the actual coins used, not just the count.
  • Count the number of ways to make the amount; why does the loop order decide whether you count combinations or permutations?
  • Bring the longest common subsequence table down from O(m x n) to O(min(m, n)) memory.

Denormalise tenant onto revisions and backfill it live

Hard · denormalisation · online migration · backfill

resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.

Approach

  1. Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
  2. Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
  3. Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
  4. Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.

Follow-up

  • The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
  • How do you verify the backfill actually finished, given rows are still being inserted while it runs?

Write the update path that detects a concurrent edit

Medium · optimistic concurrency · transactional outbox · audit history

resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.

Approach

  1. One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
  2. Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
  3. State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
  4. Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.

Follow-up

  • A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
  • Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?

Explain the concept of object-oriented programming and its benefits.

Medium · Technical / Domain Questions

Approach

  1. Define the four pillars with one concrete example each: encapsulation (an Order class keeps its line items private and exposes add_item), abstraction (callers use a PaymentMethod interface, not card-network details), inheritance (a subclass reuses and extends a base type), polymorphism (one call, charge(), dispatches to the right implementation at runtime).
  2. Tie each pillar to a benefit you can defend: encapsulation protects invariants, abstraction and polymorphism let you add a new implementation without editing callers (open/closed), and small cohesive classes are easier to unit test and mock.
  3. Name the costs as well: deep inheritance trees couple subclasses to base-class internals (the fragile base class problem), and over-abstracted code adds indirection with no second implementation to justify it.
  4. Say you prefer composition over inheritance for behaviour that varies independently, and show it: an Order holds a PricingStrategy instead of subclassing into BulkOrder, DiscountOrder and so on.
  5. Relate it to the languages the role lists: Java enforces classes and interfaces, while Python relies on duck typing and abc.ABC, and JavaScript uses prototypes with class syntax on top.

Follow-up

  • When would you choose an interface over an abstract class, and how does that differ between Java and Python?
  • Give an example that violates the Liskov substitution principle and say how you would fix it.
  • Where does OOP get in the way, and when would a plain function or data class be the better design?

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

Medium · Technical / Domain Questions

Approach

  1. Choose a problem with a real technical constraint (a latency budget, data volume, a race condition, a memory ceiling) and state the measurable symptom and its impact in one or two sentences before anything else.
  2. Walk through the diagnosis as a sequence of hypotheses and the evidence that confirmed or killed each one: profiler output, query plans, logs, a reproduction you built. This is where the depth of the answer lives.
  3. Name at least two solutions you considered, the trade-off between them (complexity, risk, cost, time to ship) and why you picked the one you did; say clearly which decisions were yours.
  4. Close with a number: before and after latency, error rate or cost, plus how you verified the fix held in production and what guard you added (a test, an alert, a load test).
  5. Finish with what you would do differently; a candid lesson reads stronger than a flawless story.

Follow-up

  • What was the hardest dead end, and how did you decide to abandon it?
  • How did you confirm your change caused the improvement rather than a coincident traffic or config change?
  • If the constraint had been ten times tighter, what would you have built instead?

What are the differences between REST and SOAP APIs?

Medium · Technical / Domain Questions

Approach

  1. Frame the category difference first: REST is an architectural style built on HTTP semantics (resources identified by URLs, standard verbs, stateless requests), while SOAP is a protocol with a mandated XML envelope, usually sent as HTTP POST, and described by a WSDL contract.
  2. Compare the payloads and tooling: REST commonly uses JSON (any representation is allowed), is light to call from a browser or mobile client, and needs no generated stubs; SOAP is XML-only, verbose, and typically used with code generated from the WSDL.
  3. Contrast error handling and caching: REST signals outcomes with HTTP status codes and can use HTTP caching for GET; SOAP returns a Fault element in the body, and since its calls are POSTs, standard HTTP caches do not help.
  4. Cover reliability and security: REST relies on HTTPS plus OAuth or tokens, and on idempotent verbs (GET, PUT, DELETE) or idempotency keys for safe retries of POST; SOAP has WS-* standards such as WS-Security and WS-ReliableMessaging for message-level guarantees.
  5. Give the decision rule: REST for public, web and mobile APIs; SOAP when integrating with an existing enterprise or financial system that already exposes a strict WSDL contract.

Follow-up

  • How would you make a REST endpoint that creates an order safe for a client to retry after a timeout?
  • How would you version a REST API without breaking existing clients?
  • Where would you pick gRPC or GraphQL over either of these?

Describe how you would design a new feature for the Boxed platform.

Medium · Problem-Solving / Case Studies

Approach

  1. Start from the user problem and the success metric before any boxes and arrows; pick one concrete e-commerce feature to make it tangible, for example a back-in-stock notification, and state the smallest version worth shipping.
  2. Define the API and data model: POST and DELETE on a subscription resource, a table of (user_id, product_id, created_at, notified_at) with a unique constraint on (user_id, product_id) so repeated clicks do not create duplicates.
  3. Lay out the flow: when inventory for a product goes from zero to positive, publish an event to a queue; a worker reads the subscribers in batches, sends notifications through the email or push provider, and sets notified_at so a retry does not send twice.
  4. Cover failure and scale: idempotent consumers for at-least-once delivery, rate limits toward the email provider, and what happens when far more people subscribed than units returned (notify in order, or notify all and let checkout decide).
  5. Ship it safely: behind a feature flag, instrumented with events for subscribe, notify, click and purchase, and ideally rolled out as an A/B test against the metric you named at the start.

Follow-up

  • Fifty thousand people subscribed and two hundred units came back in stock; how does the design behave?
  • How would you measure whether the feature drove incremental purchases rather than shifting them?
  • Which parts would you put in the existing service, and which would justify a separate one?

If you had limited resources, how would you prioritize feature development?

Medium · Problem-Solving / Case Studies

Approach

  1. Make the goal explicit first: name the one metric or business outcome this period is meant to move, because priority only makes sense relative to it.
  2. Score candidates with a simple, explainable model such as RICE (reach x impact x confidence / effort) or cost of delay divided by effort, and admit that the inputs are estimates you will revisit.
  3. Account for what scores miss: dependencies that unblock other work, risk you should retire early (an unproven integration), compliance or reliability fixes that are not optional, and tech debt that is slowing every other item.
  4. Cut scope rather than spreading people thin: ship the smallest version of the top item end to end, then reassess with real data instead of running several half-finished projects in parallel.
  5. Say no visibly: write down what is deferred and why, and agree the trade-off with stakeholders so the decision is shared.

Follow-up

  • Two stakeholders each insist their feature is the top priority; how do you settle it?
  • How would you weigh a reliability fix that no user has asked for against a requested feature?
  • How do you know, after shipping, whether you prioritised correctly?

What metrics would you use to measure the success of a new feature?

Medium · Problem-Solving / Case Studies

Approach

  1. Start from the feature's goal and choose one primary metric that moves if the goal is met; for an e-commerce feature that might be conversion rate, average order value or repeat-purchase rate, depending on what the feature is for.
  2. Add guardrail metrics that must not get worse: page latency (p95), error rate, cancellations or returns, unsubscribes; plus adoption metrics (how many eligible users saw and used the feature) to separate 'did not work' from 'was not used'.
  3. Define the instrumentation before launch: the exact events, their properties, the denominator for each rate, and a baseline from current data.
  4. Measure causally with an A/B test where possible: randomise by user, size the sample from the baseline rate and minimum detectable effect, run full weekly cycles, and do not stop early on a peek at significance.
  5. Plan the decision in advance: what result ships the feature, what rolls it back, and how you will treat a novelty effect that fades after launch.

Follow-up

  • The primary metric rose but a guardrail fell; how do you decide whether to ship?
  • You cannot run an A/B test; how would you estimate the feature's impact instead?
  • Engagement with the feature is high but revenue is flat; what would you investigate?

How would you handle scope creep in a project?

Medium · Problem-Solving / Case Studies

Approach

  1. Prevent it first: agree on written scope with acceptance criteria and an explicit out-of-scope list at the start, so there is a baseline to compare new requests against.
  2. Triage each new request instead of absorbing it silently: estimate its effort and its effect on the date, and classify it as essential to the goal, nice to have, or a separate project.
  3. Make the trade-off explicit to the stakeholder: adding this means moving the date, adding people, or dropping something of similar size. Let them choose with the cost visible.
  4. Park deferred requests in a backlog for a follow-up release so the requester sees them recorded, not refused.
  5. Watch for creep from inside engineering as well: extra generality or polish nobody asked for counts too, and you handle it the same way.

Follow-up

  • A senior stakeholder adds a requirement a few days before launch; what exactly do you say?
  • How do you tell legitimate learning that should change the scope from creep?
  • Describe a time scope did grow; what did it cost and what would you change?

Design a URL shortening service. What considerations would you take into account?

Medium · System Design / Architecture

Approach

  1. Pin down requirements and scale: create a short link, redirect, optional custom alias and expiry, click analytics; reads far outnumber writes, so the redirect path is what you optimise.
  2. Choose key generation and justify it: base62-encode a unique ID (seven characters give 62^7, about 3.5 trillion codes), with ID ranges handed out in blocks to each app server so there is no single counter bottleneck; or random codes with a uniqueness check on insert. Sequential codes are guessable, so shuffle or obfuscate them if enumeration matters.
  3. Store mappings in a key-value store or a table keyed by short code, and put a cache such as Redis in front of the redirect path so hot links never hit the database.
  4. Pick the redirect status deliberately: 301 is cached by browsers, which cuts load but hides repeat clicks from analytics; 302 or 307 sends every click to your servers. Write click events to a queue and aggregate them asynchronously so analytics never slows the redirect.
  5. Cover abuse and lifecycle: rate-limit link creation, check target URLs against malware or phishing lists, and expire old links with a TTL or a background cleanup job.

Follow-up

  • Should the same long URL always return the same short code? What does each choice cost?
  • How would you serve redirects from several regions with low latency?
  • How do you stop someone from enumerating every short link?

How would you architect a system to handle millions of users?

Medium · System Design / Architecture

Approach

  1. Start with numbers: users, requests per user and read/write ratio. For example, 1 million daily users making 20 requests each is 20 million a day, about 230 requests per second on average, with peaks several times higher.
  2. Keep the application tier stateless behind a load balancer with autoscaling, holding sessions in a shared store or signed tokens so any instance can serve any request.
  3. Take load off the database in stages: a CDN for static assets, a cache such as Redis for hot reads, read replicas for read-heavy queries, then shard by a key such as user_id once a single primary cannot take the write load.
  4. Move slow or bursty work off the request path onto a message queue (emails, order processing, analytics) so spikes are absorbed by consumers instead of user-facing latency.
  5. Plan for failure and visibility: multiple availability zones, health checks, timeouts and circuit breakers on dependencies, and metrics, logs and traces to find the bottleneck before users do.

Follow-up

  • A user updates their profile and immediately sees old data from a read replica; how do you fix that?
  • One product page becomes extremely hot; how do you keep it from overloading one cache node or shard?
  • Which component do you expect to fail first as traffic grows tenfold, and why?

Discuss the trade-offs between microservices and monolithic architecture.

Medium · System Design / Architecture

Approach

  1. Give the monolith its due: one deployable and one codebase, in-process calls, ACID transactions across the whole domain in one database, and simple local debugging and refactoring. It suits small teams and early products.
  2. Name where the monolith hurts: every change redeploys everything, the whole app scales as one unit, many teams contend over one codebase and release train, and a memory leak in one module can take the whole process down.
  3. Give microservices the matching pros and costs: independent deploys and scaling, fault isolation and team ownership, paid for with network latency and partial failures, no cross-service transactions (sagas and eventual consistency instead), distributed tracing, and much more infrastructure such as container orchestration and per-service pipelines.
  4. State a decision rule: start with a modular monolith with clear internal boundaries, and extract a service along a bounded context when a specific pressure appears (a component with very different scaling needs, or teams blocked by shared deploys), using the strangler-fig pattern.
  5. Call out the anti-pattern: services sharing one database are a distributed monolith, with all of the network cost and none of the independence.

Follow-up

  • Checkout touches orders, payments and inventory in separate services; how do you keep them consistent?
  • Which piece of a monolith would you extract first, and how would you migrate traffic safely?
  • How does testing change once you have twenty services instead of one application?

Explain how you would ensure data consistency in a distributed system.

Medium · System Design / Architecture

Approach

  1. Decide the consistency each operation needs: strong consistency where a stale read costs money (stock decrements, payments), eventual consistency where it does not (view counts, recommendations). Use CAP or PACELC to name the availability and latency you give up.
  2. Use replication settings to match: a single leader with synchronous replicas for strong reads, or quorums in leaderless stores where R + W > N guarantees that read and write sets overlap.
  3. Avoid the dual-write problem with a transactional outbox: write the business row and an outbox event in the same local transaction, and have a relay publish the event, so the database and the message broker cannot disagree.
  4. For multi-service workflows prefer sagas with compensating actions (release the reserved stock if payment fails) over two-phase commit, which blocks participants when the coordinator fails.
  5. Make every consumer idempotent, since at-least-once delivery means duplicates (dedupe on an event or idempotency key), and handle concurrent writes with optimistic locking: UPDATE ... SET version = version + 1 WHERE id = ? AND version = ?, retrying when zero rows change.

Follow-up

  • Two customers buy the last unit at the same moment; how does your design prevent overselling?
  • An event is delivered twice and processed twice; what goes wrong and how do you stop it?
  • During a network partition, which operations would you keep available and which would you refuse?

What strategies would you use to optimize database performance?

Medium · System Design / Architecture

Approach

  1. Measure before changing anything: find the slowest and most frequent queries from the slow-query log or pg_stat_statements, then run EXPLAIN ANALYZE to see sequential scans, bad row estimates and expensive sorts.
  2. Index for the actual query shape: a composite B-tree index with equality columns first and the range or sort column last, or a covering index for index-only scans; remember each index slows writes and uses storage.
  3. Fix query patterns in the application: remove N+1 queries with joins or batched IN lookups, select only needed columns, and replace large OFFSET pagination with keyset pagination (WHERE id > last_seen ORDER BY id LIMIT n).
  4. Scale the infrastructure only after that: connection pooling, caching hot reads, read replicas for read-heavy traffic, partitioning very large tables by time or key, and selective denormalisation where joins dominate.
  5. Keep the database healthy: up-to-date statistics (ANALYZE), vacuum in Postgres, and monitoring of lock waits and connection counts so regressions are caught after deploys.

Follow-up

  • You added an index but the query still does a full scan; what could cause that?
  • A table is write-heavy and also needs fast filtered reads; how do you balance the two?
  • When would you move part of this data to a NoSQL store instead of tuning SQL further?

How would you approach debugging a production issue?

Medium · Problem-Solving / Case Studies

Approach

  1. Start with impact and mitigation: who is affected, how badly, and whether a rollback, feature-flag switch-off or traffic shift stops the bleeding before root cause is known. Say that you would communicate status early.
  2. Build a timeline of what changed: deploys, config or flag changes, schema migrations, dependency or infrastructure events, traffic spikes. Line it up against when error rates or latency moved on the dashboards.
  3. Narrow the scope with data: is it all users or one region, endpoint, browser or customer segment? Follow one failing request end to end through logs and traces using a request or correlation ID.
  4. Form one hypothesis at a time, test it (reproduce in staging, compare a failing and a passing request, bisect commits), and keep the trigger separate from the cause, since a deploy may only expose an older latent bug.
  5. Close the loop: ship the fix with a regression test, confirm the metric recovered, and write a blameless postmortem with action items such as the missing alert or the test that would have caught it.

Follow-up

  • The bug cannot be reproduced locally and only appears under peak load; what do you do next?
  • Rolling back did not fix it; what does that tell you, and where do you look now?
  • How do you tell a real cause from something that merely happened at the same time?

Suggested practice checklist

The plan follows the reported loop: fundamentals for the coding assessment first, then system design and domain answers for the onsite, then stories for the manager and leadership conversations, and a full mock to finish.

Day 1 — Map the loop and choose your language

  • Write the five reported rounds in order and mark which question types you have not practised in the last month.
  • Choose Python, Java or JavaScript for all coding practice this week and set up a plain editor with no autocomplete.
  • List the requirements candidates describe (cloud such as AWS or Azure, Git, SQL and NoSQL, Docker, Kubernetes, React or Angular) and rate your real experience with each.

Deliverable: A one-page loop map with the weakest question types marked, plus a rated skills list that decides what to cover on days 2 to 6.

Day 2 — Hashing, searching and complexity

  • Solve the two-numbers-that-add-up-to-a-target problem three ways (nested loop, sort with two pointers, hash map) and write the time and space complexity of each.
  • Write iterative binary search from memory, then a variant that finds the first position of a value, and run empty, single-element, duplicate and absent-target tests.
  • Practise explaining the complexity and trade-offs of each solution aloud in two or three sentences.

Deliverable: Tested two-sum and binary search code in your chosen language, and a spoken complexity summary for each approach.

Day 3 — Linked lists and dynamic programming

  • Reverse a linked list iteratively and recursively, and test the empty list and a single node.
  • Solve two dynamic programming problems, such as climbing stairs and coin change, top-down with memoisation and bottom-up, writing the state and recurrence first.
  • Say the time and space complexity of each version and which one you would ship.

Deliverable: Working iterative and recursive list reversal plus two dynamic programming solutions in both forms, each with its recurrence written out.

Day 4 — System design on the reported topics

  • Design a URL shortener end to end: requirements, ID generation, storage choice, the redirect read path, caching and a ten-times traffic scenario.
  • Write a comparison of microservices and a monolith with a concrete case for each and the operational cost of splitting a service.
  • Outline how you would keep data consistent in a distributed system using transactions, idempotent writes, eventual consistency and compensating steps, and when each applies.
  • Write a database performance checklist: query plans, indexes, caching, read replicas and partitioning, and how you would measure before changing anything.

Deliverable: A one-page URL shortener design, a monolith-versus-microservices trade-off table, a consistency options list and a database tuning checklist.

Day 5 — Domain answers, debugging and feature cases

  • Answer the object-oriented programming question with a worked example of encapsulation, inheritance, polymorphism and abstraction, and write a REST versus SOAP comparison covering format, contract and error handling.
  • Write a production-debugging routine and a feature design for the Boxed platform with the success metrics you would track, and rehearse both aloud.

Deliverable: Spoken answers for object-oriented programming, REST versus SOAP, production debugging and feature metrics, plus two completed SQL drills.

Day 6 — Build the behavioral story bank

  • Write short outlines for four stories (pressure, prioritising, conflict, a hard technical problem) with the situation, your decision, the result and what you would change.
  • Write specific answers on how you used Git on a team and what you ran on a cloud platform, naming practices and services.
  • Prepare answers on motivation, team communication and prioritising feature work with limited resources, then say each aloud and trim it.

Deliverable: A story bank with an outline per behavioral prompt and written answers on version control and cloud experience.

Day 7 — Full mock loop

  • Reverse a linked list cold, then design the URL shortener cold, speaking your reasoning aloud throughout.
  • Answer the hard-technical-problem and scope creep questions aloud and record them.
  • Review the recordings, fix unclear or missing complexity statements and decisions, and pick one weak area to repeat.

Deliverable: Recordings of one coding problem, one design and two answers, with a short list of fixes for each.

Stories for the manager and leadership conversations

Behavioral questions in this loop are about how you handle pressure, competing work, disagreement and day-to-day communication. The role as candidates describe it involves working with product managers, designers and other engineers, reviewing code and joining agile ceremonies, so pick stories from that kind of work. A hiring manager interview and a call with senior leadership are both reported, so prepare each story at two levels: the full detail and a plain two-sentence version.

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

How do you handle version control in a collaborative environment?

Medium · Technical / Domain Questions

Approach

  1. Name the workflow you actually used: short-lived feature branches off main, small pull requests, and a protected main that needs review and passing CI before merge. If the team used trunk-based development or Gitflow, say which and why it suited the release rhythm.
  2. Explain the merge strategy with reasons: squash-merge keeps main readable, rebase your own unpushed branch to stay current, and never rewrite history on a branch other people have pulled.
  3. Cover conflicts: pull or rebase often so they stay small, resolve by understanding both changes (and asking the author when intent is unclear), then re-run tests before pushing.
  4. Cover recovery: use git revert on shared branches to undo a bad commit safely, git bisect to find the commit that introduced a regression, tags to mark releases and hotfix branches cut from the released tag.
  5. Anchor everything in one real team (size, number of repos, how releases went out) instead of reciting commands.

Follow-up

  • When would you rebase and when would you merge?
  • A bad commit is already on main and deployed. Walk me through your steps.
  • Two people changed the same function and the conflict markers do not show the intent. What do you do?

Can you discuss your experience with cloud services?

Medium · Technical / Domain Questions

Approach

  1. Name the provider and the workload first (the requirements candidates describe give AWS and Azure as examples): what ran there, which services handled compute, storage, database, queueing and networking, and which parts were yours versus a platform team's.
  2. Describe how code reached the cloud: the CI/CD pipeline, infrastructure as code if you used it, the environments, and how you rolled back. Mention Docker or Kubernetes only if you really used them.
  3. Pick two decisions with trade-offs, such as a managed database versus self-hosting, autoscaling versus fixed capacity, or cost versus latency, and say what you measured to decide.
  4. Cover operations: least-privilege IAM roles, secrets handling, logs, metrics and alerts, and one incident or cost surprise with the change you made afterward.
  5. State your depth honestly: which services you operated and which you only consumed. A precise, smaller claim holds up better than a broad one.

Follow-up

  • How did you keep secrets and permissions locked down?
  • What did it cost, and what did you do to bring that down?
  • Tell me about a time a cloud service failed or throttled you. What did you do?

Describe a time when you had to work under pressure. How did you handle it?

Medium · Behavioral / Leadership

Approach

  1. Choose a situation with a real constraint, such as a moved deadline, a production incident or a release blocked late, and state the constraint with a date or number in one or two sentences.
  2. Spend most of the answer on your decisions: how you triaged, what you cut or deferred and who agreed, what you handed to teammates, and which checks (tests, review) you refused to skip.
  3. Show communication under pressure: the status update you sent, to whom, and how often you repeated it.
  4. Finish with the result and what you changed afterward, such as a runbook, an alert or a smaller first release. A story that is only extra hours with no decision in it is the common way this answer fails.

Follow-up

  • What did you decide not to do, and who signed off on that?
  • Would you handle it the same way today?
  • What did you learn about your own limits in that situation?

How do you prioritize tasks when managing multiple projects?

Medium · Behavioral / Leadership

Approach

  1. State a method before the story: list everything, tag each item by user or business impact, deadline, dependency and effort, then rank. Impact versus effort or a simple scoring sheet works if you explain how you used it.
  2. Use a concrete case with two or three competing projects: say what shipped first, what slipped, and how you told the affected people rather than letting a date pass silently.
  3. Show how you handle change: re-rank when a production bug or a new request arrives, and negotiate scope with the product manager instead of absorbing the extra work.
  4. Include how you protect focus, for example limiting work in progress and batching reviews and meetings.

Follow-up

  • Two stakeholders both say their request is the top priority. What do you do?
  • A production bug lands in the middle of a sprint. What moves?
  • Tell me about something you deliberately chose not to do.

Can you give an example of how you resolved a conflict within your team?

Medium · Behavioral / Leadership

Approach

  1. Pick a technical or process disagreement, such as a design choice, review feedback or who owns a task, rather than a personality clash, and give each position fairly in a sentence.
  2. Show how you understood the other side: you asked questions, restated their reasoning and found the underlying concern, whether risk, deadline or maintenance cost.
  3. Move from opinion to evidence: a small prototype, a benchmark or agreed decision criteria. Escalate to a lead only after trying to settle it directly, and say that you did.
  4. Give the outcome, including any point where you changed your own mind, and the working relationship afterward. A story where you were simply right and the other person was wrong undermines the answer.

Follow-up

  • What if the other person still disagreed after seeing the data?
  • What did you change about how you give or take review feedback?
  • When did you decide to escalate, and to whom?

What motivates you to do your best work?

Medium · Behavioral / Leadership

Approach

  1. Answer with specific kinds of work, not adjectives: for example shipping something users touch, removing a performance bottleneck, or helping teammates through code review. Pick the one that is true for you.
  2. Back it with one example where it showed: what you did, what changed and what evidence it mattered.
  3. Connect it to the work candidates report for this role, such as building features with product managers and designers, code review and performance work. Do not claim knowledge of Boxed's internals.
  4. Be ready to say what drains you as well, such as unclear requirements, and how you manage it.

Follow-up

  • Tell me about a recent time you felt that way at work.
  • What do you do when the work in front of you is routine?
  • What kind of work would not motivate you, and how would you handle it?

How do you ensure effective communication with team members?

Medium · Behavioral / Leadership

Approach

  1. Describe your actual mechanisms: pull request descriptions that say why, short design notes before large changes, a written record of decisions, standup and sprint updates, and the point where an async thread should become a call.
  2. Tailor to the audience: with product managers and designers talk about user impact and trade-offs, with engineers talk about interfaces, risks and test plans.
  3. Give one case where communication failed, such as a misread requirement or a surprise delay, and the specific habit you changed, for example confirming requirements in writing or flagging slips early.
  4. Show listening: restate what you heard to confirm understanding and ask for feedback on your own updates.

Follow-up

  • How do you deliver bad news about a slipping date?
  • How do you work with someone who rarely responds?
  • How do you handle a teammate in a different time zone?