cswork / libraryOpen practice workspace

Interview guides · Yum! Brands

Yum! Brands Software Engineer Interview Guide

Yum! Brands Software Engineer interview guide: the three reported rounds, coding, design and behavioural questions, worked exercises and a 7-day plan.

The 60-second brief

Yum! Brands is the parent company of KFC, Pizza Hut, Taco Bell and The Habit Burger Grill. Software Engineers there work on the digital commerce, logistics and kitchen management platforms behind those restaurants, including point-of-sale systems, delivery dispatch, e-commerce, localized digital menus and transactional APIs.

This guide covers the three reported stages of the Yum! Brands Software Engineer loop (a Talent Acquisition conversation, technical evaluations, and final interviews), the reported coding, practical engineering, conceptual and behavioural questions, and a seven-day plan that works through each category using the guide's worked exercises.

Focus areas

  • Make every write idempotent under client retries
  • Bound blast radius with per-tenant concurrency limits
  • Keep money in integer minor units

Overview

The reported questions follow that work closely: a shortest path on a grid-based delivery map, a rate limiter for an API endpoint, a slow search over millions of menu items, caching for a read-heavy restaurant location finder, SQL versus NoSQL for a global order history service, and refactoring an ordering platform from a monolith into microservices without downtime. If you prepare for read-heavy lookups, traffic spikes, safe migrations and data you cannot afford to get wrong, you will have covered the reported design and data questions.

Beyond the algorithm problems, be ready to discuss REST API design and to defend a database choice for a concrete service, since both come up in the reported conceptual questions. Candidates also report practical engineering tasks: reviewing a short Python script for bugs and security problems, unit-testing a service that depends on third-party payment APIs, and debugging an intermittent memory leak in production. Code review and pair programming appear among the reported topics, so practise reading and extending existing code as well as writing it from scratch.

The Yum! Brands interview process

Yum! Brands candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.

Talent Acquisition Conversation

The first reported stage is a conversation with the Talent Acquisition team about your background, your career aspirations and how you align with the company's values. Keep the facts you give here (roles, dates, team sizes, your own part in each project) consistent with what you say in later rounds. Use the conversation to confirm the format of the technical evaluations, which language you may use, whether system design is in scope at your level, and whether the steps differ for your team, location or seniority.

What to demonstrate

  • How clearly you summarise your background and the engineering work you want to do next
  • Whether your career aspirations fit the Software Engineer role you applied for
  • How you align with the company's values, which candidates report as part of this conversation

How to prepare

  • Write a short summary of your last two roles: the systems you worked on, your specific part in them, and one result you can back with a number
  • Prepare a direct answer to why this role that refers to the kind of work it involves (ordering, delivery and restaurant platforms) rather than general enthusiasm
  • Bring questions for the recruiter: how many technical evaluations to expect, whether any involve live coding, pair programming or code review, and which language you may use

Technical Evaluations

Candidates describe this stage as a series of evaluations that test both theoretical knowledge and practical coding skills. The reported coding and conceptual categories are good practice for that description. The reported coding questions are standard data-structure problems: reversing a linked list iteratively and recursively, maximum sum contiguous subarray, shortest path on a grid, lowest common ancestor and a basic rate limiter. The reported conceptual questions cover SQL versus NoSQL, dependency injection, REST versus GraphQL and caching. Code review and pair programming also appear among the reported topics, so practise reading and critiquing code as well as writing it. Clarify the input first, state a correct approach and its complexity, then write code you can trace by hand.

What to demonstrate

  • Whether your code is correct on edge inputs such as an empty list, a single node, or an array where every number is negative
  • Whether you can state and justify time and space complexity, including the recursion stack in a recursive solution
  • Whether you explain core concepts through a concrete choice for a scenario rather than a list of definitions
  • Whether you can review or extend existing code, since code review and pair programming appear in the reported topics

How to prepare

  • Solve reverse linked list both ways and explain why the recursive version uses O(n) stack space and the iterative one uses O(1)
  • Practise grid shortest path with BFS, marking cells visited when they are enqueued, and Kadane's algorithm initialised from the first element so an all-negative array returns its largest element
  • For each conceptual question, pick one scenario, such as a global order history service or a restaurant location finder, and prepare the choice you would make for it
  • Review a short Python script aloud, naming bugs first, then security issues, then performance problems

Final Interviews

Candidates describe the final stage as meetings with engineering leaders, peers and cross-functional partners that assess system design and behavioural alignment. The reported design and architecture questions are good practice for it: refactoring a monolith into microservices without downtime for ordering platforms, caching for a read-heavy restaurant location finder, choosing a database for a global order history service, and optimising a slow search over millions of menu items. The reported behavioural prompts cover trade-offs under deadline pressure, disagreements with product managers, an accomplishment you drove, and a feature you delivered late. Cross-functional partners may be in the room, so practise explaining your technical choices in terms a non-engineer can follow.

What to demonstrate

  • Whether a design starts from requirements and access patterns (read versus write volume, traffic spikes, users in many regions) before components are drawn
  • Whether you can plan a change safely, with incremental rollout and a rollback path, instead of a single cutover
  • Whether your behavioural stories show your own decisions, how you communicated with stakeholders, and what you learned
  • Whether you can explain a technical trade-off to cross-functional partners who are not engineers

How to prepare

  • Sketch the monolith-to-microservices migration as a sequence: extract one capability behind a routing layer, run the old and new paths side by side, shift traffic gradually, and keep a rollback at every step
  • Prepare the location-finder cache in detail: what is cached, the key, the expiry, how an updated restaurant record invalidates the entry, and how you prevent many requests recomputing the same missing key at once
  • Write STAR outlines for the reported behavioural prompts, each with a specific result and one thing you would change
  • Practise explaining one design decision twice, first to an engineer and then to a product manager

Where candidates lose points

Returning 0 for an all-negative array in the maximum subarray question

If you initialise the running best to 0, Kadane's algorithm returns 0 when every element is negative, even though the correct answer is the largest element. Initialise both the current sum and the best sum from the first element. Test [-3, -1, -2] (answer -1) and a single-element array before you say you are done. Apply the same habit to the linked-list reversal: test an empty list and a single node, and state that the recursive version uses O(n) stack space.

Using DFS for the grid delivery-map shortest path, or marking cells visited too late

On an unweighted grid, breadth-first search finds the shortest path. Depth-first search finds a path, but not necessarily the shortest. Mark a cell visited when it is enqueued rather than when it is dequeued, or the same cell enters the queue many times. State O(rows x cols) time and space, and handle a blocked start or target. Ask whether moves are four- or eight-directional and whether some cells cost more to cross, because weighted cells call for Dijkstra instead of BFS.

Answering conceptual questions with textbook definitions and never making a choice

SQL versus NoSQL and caching are reported with a scenario attached: a global order history service and read-heavy restaurant location finders. Give the definition in one sentence, then decide for that scenario. For order history, name the access patterns (by customer, by order id, by restaurant and date), the consistency an order needs, how the data grows, and what your choice gives up. The REST versus GraphQL question asks when you would prefer each without naming a scenario, so pick one yourself, such as an API serving both mobile and web clients, and decide for it. If your answer ends on 'it depends' without a decision, it misses what the question is asking.

Unit-testing a payment-dependent service against the live provider, or only on the happy path

For the reported unit-testing question, put the payment provider behind an interface you own, inject it, and replace it with a fake in unit tests. That is also the practical case for dependency injection. Then list the cases a happy-path test misses: a declined card, a timeout after the provider may already have charged, a duplicate callback, a malformed response, and currency rounding. Keep a small set of sandbox or contract tests separate from the fast unit suite.

Planning a big-bang rewrite for the monolith-to-microservices question

The reported question requires no downtime for ordering platforms, so a single cutover is the wrong answer. Extract one capability at a time behind a routing layer (the strangler pattern), keep data consistent while both paths run, shift traffic in small steps while watching error and latency metrics, and keep a rollback at every stage. Also name what you would not split out first, such as a component that shares heavy transactions with the rest, and explain why.

Questions & practice

Write a function to reverse a linked list, both iteratively and recursively, and explain the space-time complexity of each approach.

Medium · data structures and algorithms

Approach

  1. Walk one small example through your approach before writing the whole thing.
  2. Name the brute-force solution and its complexity before improving on it.
  3. Restate the input: its shape, its size, and what is guaranteed about it.

Follow-up

  • Which test case would catch an off-by-one here?
  • What is the worst case, and how likely is it on real data?

Given an array of integers, find the contiguous subarray with the largest sum and return its sum.

Medium · data structures and algorithms

Approach

  1. Restate the input: its shape, its size, and what is guaranteed about it.
  2. Choose the data structure from the access pattern, not from familiarity.
  3. State the target complexity and say which constraint rules the naive version out.

Follow-up

  • How does this change if the input no longer fits in memory?
  • Which test case would catch an off-by-one here?

How would you implement a basic rate limiter for an API endpoint to prevent abuse?

Medium · data structures and algorithms

Approach

  1. Walk one small example through your approach before writing the whole thing.
  2. Restate the input: its shape, its size, and what is guaranteed about it.
  3. State the target complexity and say which constraint rules the naive version out.

Follow-up

  • What is the worst case, and how likely is it on real data?
  • Which test case would catch an off-by-one here?

Find peak concurrent sandbox usage from run intervals

Medium · sweep-line · intervals · concurrency-caps · null-semantics

Given up to 5 million job_run rows for one tenant over one day, with run_id, started_at, finished_at, status and wall_clock_limit_seconds, report the maximum number of sandboxes running at once, the earliest instant that maximum is reached, and the first run_id that would breach a per-tenant cap of C. started_at is null while a run is queued; finished_at is null both for runs still executing and for runs in status lost. Treat a run as occupying [started_at, finished_at). Give the complexity and state how you handle each null.

Approach

  1. Turn each run into two sweep events, (started_at, +1) and (end, -1), then sort the 2n events by timestamp with -1 ordered before +1 at equal timestamps. That tie-break is what makes the interval half-open, so a run finishing at 10:00:00 and one starting at 10:00:00 never overlap.
  2. Decide each null out loud before sweeping, because each choice moves the answer. A null started_at means queued and contributes nothing. A null finished_at with status running or leased is clipped to the window end. Status lost has no observed end at all, so clip it at started_at + wall_clock_limit_seconds on the grounds that the supervisor owns the timeout, and record that you did. The table's check (finished_at is null or started_at is not null) guarantees you never see an end without a start.
  3. Sweep once, maintaining a running counter, the maximum, and the timestamp at which the maximum was first attained (update peak_at only on a strict increase, or you will report the last such instant instead of the earliest). Capture the first run_id whose +1 takes the counter to C+1 during the same sweep rather than in a second pass.
  4. Complexity: O(n log n) dominated by the sort, O(n) space. If rows already arrive ordered by started_at, a min-heap of end times gives O(n log k) time and O(k) space with k the peak concurrency, which is the better shape when the rows come from an index scan on (tenant_id, started_at).
  5. If second resolution is acceptable, counting-sort the endpoints into an 86,400-slot delta array and prefix-sum it: O(n + T) time and O(T) space, which beats the comparison sort at 5 million rows. It answers only at second granularity, so state which resolution the cap is defined in.

Worked solution (20 min)

  1. Write the null policy as three lines of prose first, one per case, and keep them beside the output.
  2. Emit 2n endpoint tuples (timestamp, delta, run_id) and sort on the key (timestamp, delta) so -1 precedes +1.
  3. Sweep, tracking cur, peak, peak_at updated only on a strict increase, and the first run_id whose +1 takes cur to C+1.
  4. Build a fixture with two runs where one ends exactly when the next starts, three genuinely overlapping runs, one run with a null finished_at and status running, and one with status lost and a 300-second wall_clock_limit_seconds.
  5. Re-run with every timestamp shifted by a constant and confirm the peak is unchanged while peak_at shifts by the same constant.

Expected result: Peak is 3, from the overlapping trio. The exact-handoff pair yields a peak of 1, not 2. peak_at is the start instant of the third overlapping run. The lost run occupies exactly [started_at, started_at + 300s) under the stated policy.

Verify it yourself

  • Setting peak_at on >= rather than > moves the reported instant to the last time the peak was attained. Flip it and watch the fixture change.
  • Sorting by timestamp alone, without the delta tie-break, raises the reported peak on the handoff fixture.
  • The deltas over the whole sweep sum to zero once every open-ended run has been clipped.

Follow-up

  • Now report peak concurrency per tenant for 10,000 tenants from one globally sorted stream. What changes about memory and about the sort?
  • The cap has to be enforced at dispatch rather than reported afterwards. What does the admission check look like, and where does it race?
  • How would you answer 'peak concurrency within any 5-minute window' without re-sorting?

Decide which facts an invoice line copies instead of joining

Medium · denormalisation · immutable records · foreign keys · rounding

invoice_line_item already denormalises tenant_id, which is reachable through invoice_id, and stores amount_minor even though quantity times unit_price_micros would recompute it. A reviewer asks you to normalise both away, and separately asks whether the tenant's legal name and billing address should be copied onto the invoice header. Decide each case. For every field you keep denormalised, name the read pattern or the invariant that justifies it, the anomaly the copy can develop, and the mechanism that prevents that anomaly here.

Approach

  1. Split the question into two kinds of copy, because they fail differently. A copy of a currently mutable fact is a cache: it drifts and needs invalidation. A copy of a fact frozen at write time is not a cache at all, it is the record of what happened, and normalising it away destroys information the source no longer holds.
  2. Keep tenant_id on the line. It costs 8 bytes, it leads every index on the table so no read is ever accidentally cross-tenant, and it turns a wrong join into an empty result rather than another tenant's money. Prevent the drift structurally: a unique constraint on invoice (invoice_id, tenant_id) plus a composite foreign key from the line on (invoice_id, tenant_id) makes a mismatched pair impossible, so the database enforces agreement instead of a code review.
  3. Keep amount_minor. Rounding must happen exactly once, at a named site, with a stated mode (half-even here). If readers recompute from quantity and unit_price_micros, every reader owns a rounding decision, and half-up and half-even diverge systematically across thousands of lines rather than cancelling out. A check constraint can bound the stored value but deliberately cannot re-derive it.
  4. Copy the legal name and billing address onto the invoice header, written once and never updated. The statement must show what was true when it was sealed, and the tenant record will change afterwards. This is a snapshot for the same reason source_rollup_watermark is stored per line: without it, nobody can reconstruct what the customer was told.
  5. Name the read pattern that pays for all of it. Rendering, dispute response and export are per-tenant, per-period reads over thousands of lines that would otherwise join back to slowly changing dimensions that no longer hold the historical value. The write side is a once-per-period batch, so the extra columns cost nothing that matters.
  6. Concede the case where the reviewer is right: a mutable operational attribute such as the tenant's current plan name has no business on a line. If a report wants it, join. If a statement needs the plan as of the period, that is another snapshot and it belongs on the header with the rest.

Follow-up

  • Write the composite foreign key and the unique constraint it requires on the parent. What does it cost on every line insert, and what does it do to a bulk load?
  • A tenant is renamed after being invoiced. Which rows change, and what does the customer see on last quarter's PDF?
  • Where does currency live, and what breaks if a tenant's billing currency changes between two periods?

Paginate a tenant's delivery export without skipping rows

Easy · keyset pagination · indexing · multi-tenancy

A customer exports webhook_delivery: delivery_id (bigint identity), subscription_id, tenant_id, event_id, status, attempt_count, next_attempt_at, created_at, delivered_at, updated_at. The endpoint runs select ... where tenant_id = $1 order by created_at desc limit 100 offset $2, and customers report rows missing from exports taken while new deliveries are being inserted. Write the replacement query and the index that supports it, paging a tenant's deliveries newest first at constant cost per page. State why updated_at cannot be the cursor column.

Approach

  1. Name the defect precisely. OFFSET is a position in a result set that is recomputed on every request, so a row inserted ahead of the window shifts everything back by one and the next page starts after a row the client never received. Nothing errors and no identifier gap appears, so the loss is silent.
  2. Replace the position with a value predicate over a stable, unique, indexed ordering: where tenant_id = $1 and (created_at, delivery_id) < ($2, $3) order by created_at desc, delivery_id desc limit 100. The row comparison is load-bearing: created_at alone is not unique, so ties straddling a page boundary are dropped or repeated, which is the same bug in a smaller window.
  3. Index (tenant_id, created_at, delivery_id). PostgreSQL scans a btree in either direction, so an all-DESC ORDER BY is served by an ASC index read backwards and no DESC modifiers are needed; they only matter when the ORDER BY mixes directions. Confirm the plan has no Sort node above the index scan, or the LIMIT stops being an early exit.
  4. Price both forms: keyset is one index descent plus 100 adjacent leaf entries per page, constant regardless of depth, while OFFSET still produces and discards every skipped row, so page N costs time proportional to N times the page size and a deep page on a large table goes from milliseconds to seconds.
  5. Rule out updated_at as the cursor from the precondition, not from taste: a cursor column must never change value for a row already paged past. updated_at moves on every delivery attempt, so a row the client already emitted re-enters a later page and is exported twice. created_at and delivery_id are immutable, which is the whole qualification.

Worked solution (20 min)

  1. Load about 50k deliveries for one tenant, then walk them with the OFFSET query while a writer inserts 10 rows/second, collecting every returned delivery_id.
  2. Compare the distinct ids collected against the set of ids that existed when the walk started, and record the shortfall.
  3. Repeat the walk with the keyset query and confirm every pre-existing id is returned exactly once.
  4. Run explain (analyze, buffers) on page 1 and page 500 of each form and compare shared buffer hits.

Expected result: A keyset query using the row comparison (created_at, delivery_id) < ($2, $3) with order by created_at desc, delivery_id desc limit 100, backed by (tenant_id, created_at, delivery_id) scanned backwards; plus the statement that OFFSET drops rows under concurrent insert and costs time proportional to the offset, and that updated_at is disqualified because it mutates on retry.

Verify it yourself

  • Buffer counts for page 500 are the same order of magnitude as page 1.
  • Every id present before the walk is returned exactly once when only inserts run concurrently.
  • The query plan shows no Sort node above the index scan.
  • Two rows sharing a created_at value to the microsecond are both returned across the page boundary.

Follow-up

  • The client wants a snapshot as of one instant rather than a live tail. Compare a repeatable-read transaction held open, an added created_at <= $snapshot bound, and a materialised export table.
  • A retention job deletes deliveries older than 90 days. What does a client mid-walk see, and does keyset pagination help at all?
  • The customer wants to resume an export from yesterday's last cursor. What must be true of the cursor for that to be safe?

Describe your process for debugging an intermittent memory leak in a production environment.

Medium

Approach

  1. State your assumptions explicitly before working the problem.
  2. Say what you would check first and why it is the highest-information step.
  3. Clarify what is being asked and what a complete answer contains.

Follow-up

  • How would you know your answer was wrong?
  • What assumption would you test first?

How do you approach writing comprehensive unit tests for a service that relies on third-party payment APIs?

Medium

Approach

  1. Work from the requirement backwards to the design.
  2. Say what you would check first and why it is the highest-information step.
  3. State your assumptions explicitly before working the problem.

Follow-up

  • What assumption would you test first?
  • How would you know your answer was wrong?

An idempotent create endpoint that returns a one-time secret

Easy · idempotency · race conditions · api design

POST /v1/api-keys inserts a tenant_api_key row (tenant_id, workspace_id, name, key_prefix, secret_hash, scopes, status, auth_version, created_at, expires_at) and returns the plaintext secret exactly once, since only its SHA-256 is stored. Write volume is tens per second and clients retry on timeout. Design the idempotency mechanism: what the key is scoped by, where the record lives, its retention, what happens when the same key arrives with a different body, what happens when a retry arrives while the first request is still in flight, and what a replay returns for the secret.

Approach

  1. Scope the key by tenant, not globally: uniqueness is on (tenant_id, idempotency_key), or one tenant's key collides with another's and the second caller receives a stored response for a request it never sent. Store a fingerprint of the request alongside it - method, path and a hash of the canonicalised body - so a mismatch is detectable.
  2. Let the unique constraint decide the race instead of application logic. In the same transaction as the credential insert, run INSERT INTO idempotency_record (tenant_id, key, request_fingerprint, status) VALUES (...) ON CONFLICT DO NOTHING RETURNING id; no returned row means this is a replay, and the existing record is then read. A select-then-insert here loses to itself under concurrency in exactly the way this endpoint is meant to prevent.
  3. Write the three replay outcomes as a decision table rather than as prose: same fingerprint and completed returns the stored response; same fingerprint and still in flight returns 409 with Retry-After, without blocking and without executing; different fingerprint returns 422, because replaying a stored response for a mutated body would tell the caller a credential was created for parameters it never sent.
  4. Handle the secret as the part that makes this endpoint different from an ordinary idempotent create. The plaintext cannot be regenerated from secret_hash, so either the stored response holds it - making the idempotency record a secret at rest whose retention is now the secret's exposure window - or a replay returns the key metadata without the secret and the documentation says a lost response is resolved by listing keys and revoking the orphan. The second is the safer default precisely because credentials are listable and revocable.
  5. Set retention from the client's retry budget, not from a round number: the record must outlive the SDK's maximum total retry duration, so twenty-four hours is defensible if that budget is minutes. After expiry the key is reusable and a very late retry creates a second credential, which is acceptable here only because the object is listable and revocable, and would not be for an unlistable side effect. Expire with a scheduled delete on an index over created_at.

Worked solution (20 min)

  1. Write the DDL for the idempotency record, including the unique constraint that makes the concurrent case impossible rather than unlikely.
  2. Write the four outcomes - fresh, replay-completed, replay-in-flight, fingerprint-mismatch - as a decision table with the HTTP status for each.
  3. Decide what a replay returns for the plaintext secret and write the exact sentence the API reference has to carry about it.
  4. Pick a retention and justify it from the client library's own maximum retry duration rather than from a round number.

Expected result: Unique (tenant_id, idempotency_key); the record inserted in the same transaction as the credential with ON CONFLICT DO NOTHING deciding the winner; 200 with the stored response, 409 for in-flight, 422 for a fingerprint mismatch; a documented rule that the plaintext secret is not replayed and a lost response is resolved by listing and revoking; retention exceeding the SDK retry budget, for example twenty-four hours.

Verify it yourself

  • Two concurrent requests with the same key must leave exactly one row in tenant_api_key. If the logic is select-then-insert, they will not.
  • A retry with a mutated body must not return 200. If it does, the fingerprint is not being compared or is not covering the fields that matter.
  • The retention you chose must be strictly longer than the client library's maximum total retry duration. Look that number up rather than assuming it.

Follow-up

  • Two requests with the same key arrive concurrently. Show the exact statements and say which one loses, and how it finds out.
  • The client receives a timeout, retries, and gets 409 in-flight. What should the client library do next, and for how long?
  • How does the design change if the created object is not listable - a one-off payout, say - so an orphan cannot be found afterwards?

Metering partition crash-loops and the sealing watermark freezes

Medium · poison message · at-least-once · dead-letter queue

One metering-ingest partition has stopped advancing. Lag grows linearly, the consumer restarts about every 40 seconds, and the same offset appears in every startup log while other partitions stay healthy. Events are committed in batches of a few thousand and the acknowledgement follows the commit. Sealing is six hours away and source_max_ingested_at for that partition's tenants is frozen. Give an ordered checklist, a containment action available within minutes, and the durable fix, saying what each does to exactly-once accounting.

Approach

  1. Distinguish a poison record from a capacity problem in one measurement: compare the offset and the exception across restarts. An identical pair every time is deterministic failure on one record, whereas a throughput problem still advances the offset between crashes.
  2. Read the record from a separate consumer group so the bytes can be inspected without perturbing the stuck consumer, then classify the defect: schema violation, a quantity failing the non-negative check, a null workspace, an unmappable SKU enum, or a payload past a size limit. That classification decides whether this is a producer bug or a missing consumer guard.
  3. Account for batch granularity before acting. With commits of a few thousand, one bad record fails thousands of good ones, so the blast radius is the batch. Halve the batch around the offset to isolate the record, or move to per-record error isolation so the radius becomes the record.
  4. Contain by diverting that record to a dead-letter store with its raw bytes and offset, then resume. This is safe here precisely because the acknowledgement follows the commit: the good records from the failed batch are re-consumed and absorbed by the uniqueness check on (tenant_id, idempotency_key) rather than counted twice.
  5. Make the fix durable with per-record error isolation, a bounded poison counter, and an alert on dead-letter rate rather than on lag alone, since lag only reveals this after the sealing margin has already been eaten.
  6. Check the horizon before replaying anything. The unique index lives on a daily-partitioned table and therefore includes the partition key, so it deduplicates within a day only; a replay landing on a later ingest day needs the separate dedup store or it double-counts into a tenant's bill.

Follow-up

  • Move the acknowledgement before the commit and describe exactly what is lost and what is duplicated in each of the two crash windows.
  • Sealing is in six hours and the partition will not drain in time. What do you seal on, and what does the invoice have to record so the difference is explainable later?
  • A producer replays two weeks of events next month. Which part of your fix stops holding, and what is the dedup horizon you would actually configure?

Suggested practice checklist

For a candidate senior enough that the loop turns on design and judgement rather than on whether the coding round gets finished. Five days build one system properly and then stress it; coding gets a single maintenance day, on the assumption that the risk at this level is an unexamined tradeoff rather than a missed algorithm.

Day 1 — Talent Acquisition story and linked lists

  • Write your background summary and your why-this-role answer for the Talent Acquisition conversation, and list the questions you will ask about the format and language of the technical evaluations.
  • Reverse a singly linked list both iteratively and recursively. State O(n) time for both, O(1) extra space for the iterative version and O(n) stack for the recursive one, then test empty, one-node and two-node lists.
  • Solve the reported first-unique-character question with a frequency count and a second pass (O(n) time), narrating it with the clarify, brute force, optimise, communicate framework.

Deliverable: A one-page summary for the recruiter call and two linked-list implementations with their edge-case tests.

Day 2 — Arrays, grids and trees

  • Solve maximum sum contiguous subarray with Kadane's algorithm initialised from the first element; test an all-negative array, a single element and a mixed array, and extend it to return the start and end indices.
  • Implement shortest path on a grid delivery map with BFS: mark cells visited when enqueued, return -1 when the target is unreachable, and state O(rows x cols) time and space.
  • Find the lowest common ancestor of two nodes in a binary tree recursively in O(n) time, then say how the answer changes for a binary search tree.

Deliverable: Three solutions, each with its complexity and at least three edge-case tests written beside it.

Day 3 — Rate limiting and the worked concurrency exercise

  • Implement a token-bucket rate limiter keyed by client. Explain why a fixed window can let through up to twice the limit across a window boundary, and compare it with a sliding log and a sliding-window counter.
  • Decide where the limiter state lives when several API servers share one limit, for example in a shared store such as Redis, and what happens to requests if that store is unavailable.
  • Work this guide's peak concurrent usage exercise (drill-coding-3): order end events before start events at equal timestamps, and confirm the handoff fixture reports a peak of 1.

Deliverable: A working rate limiter with a written comparison of three algorithms, plus the sweep-line exercise checked against its fixtures.

Day 4 — Data questions: order history, menu search and pagination

  • For SQL versus NoSQL for a global order history service, write out the access patterns first, then make a choice and name what it costs.
  • For the slow search over millions of menu items, go through the steps: read the query plan, add an index that matches the filter and sort, replace leading-wildcard LIKE with full-text search, and paginate the results.
  • Work this guide's keyset pagination exercise (drill-sql-2) and explain why OFFSET drops rows when new rows are inserted during the walk.
  • Work the reported SQL and Python practice question.

Deliverable: A written database decision for order history and a before-and-after plan for the menu-search query.

Day 5 — Practical engineering: review, tests and debugging

  • Review a short Python script aloud, naming bugs first, then security issues (injection, secrets in code, unchecked input), then performance problems, and phrase each point as you would in a real review comment.
  • Design unit tests for a service that calls a third-party payment API: inject the client, fake it, and cover declines, timeouts, duplicate callbacks and malformed responses.
  • Write your process for an intermittent production memory leak: confirm growth with metrics, capture heap snapshots at intervals, compare them, check unbounded caches and listeners that are never removed, and verify the fix under load.
  • Work the debugging drill on the crash-looping metering partition (drill-debugging-5) as an ordered checklist.

Deliverable: One written code review, a test-case list for the payment service, and a memory-leak debugging checklist.

Day 6 — Design for the final interviews

  • Design caching for a read-heavy restaurant location finder: choose cache-aside or write-through, set an expiry, define invalidation when a restaurant's details change, and handle many requests missing the same key at once.
  • For REST versus GraphQL, pick one for a menu and ordering API that serves both mobile and web clients, and justify the choice with the client's data needs and caching behaviour.
  • Plan the monolith-to-microservices migration without downtime as ordered steps, each with a rollback.
  • Work this guide's idempotent create endpoint exercise (drill-design-4), since retried writes come up in any ordering or payment design.

Deliverable: Three design sketches with their trade-offs written down, and the idempotency exercise checked against its checks.

Day 7 — Behavioural stories and a full mock

  • Write STAR answers for the reported prompts: a trade-off under deadline, a disagreement with a product manager or engineer, an accomplishment you drove, and a feature you delivered late. For each, make your own actions and the result explicit.
  • Build a fact sheet for each project you will mention (team size, timeline, your role, the numbers you will quote) so the same story holds up in every conversation.
  • Run a mock with one coding problem, one design question and two behavioural prompts, and explain one design choice as if to a non-engineer.
  • Prepare questions for your interviewers about the team's current technical challenges and how it ships and reviews code.

Deliverable: Polished STAR answers for the reported prompts, a per-project fact sheet, and notes from the mock.

What the behavioural round is actually measuring

The reported behavioural prompts for this role ask about a technical trade-off under deadline pressure, a disagreement with product managers or engineers, an accomplishment you drove, and a feature you failed to deliver on time. Candidates report behavioural alignment being assessed in the final stage. Structure each answer with STAR (Situation, Task, Action, Result), make your own contribution explicit, give a measurable result, and in the missed-deadline story say when and how you told stakeholders. Keep each project's facts the same every time you tell it.

  1. How do you handle disagreements with product managers or other engineers regarding technical requirements?

Tell me about a time you failed to deliver a feature on time. What did you learn, and how did you communicate this to stakeholders?

Medium · behavioural and engineering judgement

Approach

  1. Give the blast radius: what could have broken, and what you measured.
  2. Name the disagreement and how you resolved it with evidence.
  3. Close with what you would do differently, concretely.

Follow-up

  • How did you know your change caused the improvement?
  • What would you do differently if you ran that again?

Share an accomplishment you are deeply passionate about. What made it successful, and how did you drive the initiative?

Medium · behavioural and engineering judgement

Approach

  1. State the situation in two sentences and spend the rest on the reasoning.
  2. Give the blast radius: what could have broken, and what you measured.
  3. Name the disagreement and how you resolved it with evidence.

Follow-up

  • What would you do differently if you ran that again?
  • What did you decide not to do, and why?

Describe a time when you had to make a difficult technical trade-off to meet a tight project deadline. What was the outcome?

Medium · behavioural and engineering judgement

Approach

  1. Close with what you would do differently, concretely.
  2. State the situation in two sentences and spend the rest on the reasoning.
  3. Give the blast radius: what could have broken, and what you measured.

Follow-up

  • How did you know your change caused the improvement?
  • What did you decide not to do, and why?