Interview guides · Waabi
Waabi Software Engineer Interview Questions & Guide 2026
System design practice for Waabi software engineer candidates: reach a data model and an API contract, not a box diagram.
The 60-second brief
Waabi develops AI for autonomous transportation.
This guide focuses on simulation-platform preparation: reproducible runs, reliable scheduling and explainable results.
Build a reproducible run, trace a worker failure, and explain why a result changed.
Focus areas
- Reproducibility
- Job scheduling
- Failure analysis
Overview
A passing simulation means little if you cannot reproduce it. Start your preparation with a small experiment runner: accept a scenario, record its inputs, run a worker and explain the result. This gives you a concrete way to discuss coding, distributed systems and debugging without pretending to know the company’s internal infrastructure.
Connect your preparation to the work. Waabi’s Simulation Platform posting describes a platform that brings together autonomy software, actor models and sensor simulation. Use the exercises below to practise the engineering decisions around that work: clear input contracts, reliable execution and results you can trace.
Match the team before choosing depth. Simulation infrastructure, motion planning and research are different paths. This guide emphasizes general software engineering rather than mathematical proofs or model training. Take the exact opening you applied for and mark which responsibilities you can support with a project example. Spend additional time on the gaps that matter to that team.
Use a deliberately small model. Our practice runner processes named scenarios and stores one result per logical run. Retries are separate attempts. Record the scenario version, software version and seed beside each result. Then identify any other dependencies that could change the outcome. Bring evidence to your explanations. Show a test that failed, the smaller input that reproduced it and the change that fixed it. Explain what the test covers and what you would investigate next.
What to prepare
Work through one experiment from input to result. Start with its contract, introduce a worker failure, then explain how you would investigate an unexpected output.
Define a reproducible run
Begin with the smallest experiment you can explain from input to result. Give the scenario and software explicit versions. Separate a logical run from each attempt to execute it. Describe what you would record if a worker dies before reporting completion.
What to demonstrate
- Correctness: Make repeated inputs and missing results distinguishable.
- Communication: Explain which assumptions are required for a comparison to be meaningful.
How to prepare
- Write a run manifest and identify every mutable dependency it references.
- Attempt the interval and duplicate-run prompts. Add an empty input and a repeated identifier to each test set.
Trace execution and recovery
Next, walk one job through a worker failure. Sketch who owns the job while it runs and what happens when that ownership expires. A second worker may start before the first stops, so the result store must reject stale completion attempts.
What to demonstrate
- Recovery: Protect the final result even when execution happens more than once.
- Tradeoffs: Separate faster retries from safe publication.
How to prepare
- Draw a lease timeline with a paused worker and a replacement worker.
- Explain how a token or version check prevents the old worker from overwriting the new result.
Explain a result you distrust
Finish with a result that changed unexpectedly. Keep input and software versions visible while you narrow the failure. Start from a repeatable small case; adding more runs before understanding the comparison can make a misleading aggregate look more convincing.
What to demonstrate
- Debugging: Separate measurement errors from behavior changes.
- Judgment: Describe what would make you halt a comparison or investigate further.
How to prepare
- Prepare a real debugging story with the observation that changed your hypothesis.
- Compare results only after checking the matched scenario set, metric definition and missing-run policy.
Where candidates lose points
Treating a seed as the whole experiment
Record the inputs that can change. A seed cannot identify a changed scenario, dependency or simulator build. Keep those versions beside the result and document which sources of nondeterminism remain.
Counting retries as fresh evidence
Count logical runs, not attempts. A worker failure should not give one scenario extra weight in a success-rate calculation. Decide which completed attempt represents the run.
Publishing a late worker result
Check ownership when committing. A lease expiring does not stop a paused process. Reject results with stale fencing tokens even if their computation finished successfully.
Comparing different scenario sets
Inspect the denominator. A higher pass rate may come from missing difficult cases. Report absent results separately and compare matched scenario IDs before drawing a conclusion.
Questions & practice
Merge overlapping simulation windows
Medium · Intervals · Sorting
Given integer intervals [start, end), reject end <= start and merge intervals that overlap or touch. Return sorted, nonoverlapping windows without changing the input.
Approach
- Start simple: Sort a copy by start, then extend the final output window when the next start is at or before its end.
- Check boundaries: Touching intervals are merged by this contract, even though their half-open sets do not overlap.
Worked solution (35 min)
- Sort a new list so the caller’s input is preserved. Validate each interval before extending the output.
- When a window touches or overlaps the final output window, replace its end with the larger end. Otherwise append a new window. Sorting dominates at O(n log n).
def merge_windows(intervals):
result = []
for start, end in sorted(intervals):
if end <= start:
raise ValueError("invalid interval")
if result and start <= result[-1][1]:
result[-1] = (result[-1][0], max(result[-1][1], end))
else:
result.append((start, end))
return result
Expected result: [(1, 5), (8, 10)] for [(3,5),(1,3),(8,10)].
Verify it yourself
- Test empty input, nested windows and reversed endpoints.
- Confirm that the original list is unchanged.
Follow-up
- How would the answer change if touching windows had to remain separate?
Deduplicate run requests
Easy · Hash sets · Idempotency
Given request IDs in arrival order, return the first occurrence of each ID while preserving order. Assume IDs are nonempty strings; reject a blank ID.
Approach
- Use a set for membership and a list for output. State the O(n) expected time and O(u) additional space.
- A bounded cache needs an expiry policy; after expiry it no longer promises global deduplication.
Follow-up
- How would you support a stream that never ends?
Count recent completed jobs
Medium · Queues · Time boundaries
Count completion events in (now − 10, now]. Events arrive in timestamp order and each contributes one. Advance the clock during idle periods too.
Approach
- Expire timestamps at or before the lower boundary. A deque gives amortized constant work per arrival.
- Treat the timestamps as arrival time; out-of-order event time needs a different contract.
Follow-up
- What happens to the result at 30 seconds with no recent events?
Select the latest successful attempt
Medium · Window functions · Retry semantics
From attempts(run_id, attempt_no, status, score), return the highest numbered successful attempt per run. The pair run_id and attempt_no is unique.
Approach
- Filter successes before ranking within each run.
- Keep failed-only runs absent from this result, then report them separately rather than calling them passes.
Worked solution (35 min)
- Filter successful attempts before applying ROW_NUMBER. Otherwise a newer failed attempt can hide an earlier valid success.
- Rank within the logical run, then select rank one. Keep attempt number in the output for traceability.
WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY run_id ORDER BY attempt_no DESC) AS rn
FROM attempts WHERE status = 'success'
)
SELECT run_id, attempt_no, score FROM ranked WHERE rn = 1;
Expected result: Run A keeps successful attempt 2 even if attempt 3 failed.
Verify it yourself
- Test a run with only failures.
- Test two successful attempts with different scores.
Follow-up
- How would you expose runs with no successful attempt?
Find scenarios missing results
Medium · Anti joins · Coverage
Given expected(scenario_id) and results(scenario_id, build_id), return expected IDs without a result for build B. Expected IDs are unique.
Approach
- Use NOT EXISTS with both the scenario match and target build condition.
- Test an ID present only in build A so it does not accidentally count as coverage for B.
Follow-up
- Should a failed run count as a missing result or a known failure?
Design a simulation job runner
Medium · Scheduling · Fencing · Recovery
Design a queue-backed runner with retries, worker crashes and one published result per logical run. Users need to inspect failures and rerun a versioned experiment.
Approach
- Separate run identity, attempt identity and worker ownership.
- Write results under an ownership check; store immutable artifacts before publishing their reference.
- Expose queue delay, attempt failures and completed logical runs as separate metrics.
Worked solution (35 min)
- Store a durable run manifest. Allocate a fresh fencing token when a worker receives ownership.
- Write artifacts under an attempt-specific path. Commit the selected artifact only if the worker still holds the current token.
- After a timeout, retry execution with a new token. Keep incomplete artifacts invisible and clean them up later.
Expected result: A late completion from an old worker cannot replace the published result.
Verify it yourself
- Pause a worker beyond its lease and finish a second attempt.
- Resume the first worker and verify its commit is rejected.
Follow-up
- What happens if artifact upload succeeds but the commit fails?
Compare two software builds fairly
Medium · Evaluation · Provenance
Design a report comparing build A and build B on a named scenario set. Some runs fail to produce a result. Users must be able to trace every summary to its inputs.
Approach
- Version the scenario set and metric definition.
- Show matched coverage and missing runs before computing a change.
- Keep result references so a reader can inspect individual cases.
Follow-up
- How would you prevent selection of only favorable scenarios?
A paused worker overwrites a newer result
Medium · Races · Distributed systems
Worker A loses its lease. Worker B completes the same run. A resumes and overwrites B. Explain the race and fix the commit boundary.
Approach
- A timeout changes ownership, not process liveness.
- Attach a monotonically increasing token to each lease and reject commits from older tokens atomically.
Worked solution (35 min)
- Reproduce the pause between computation and commit. Check which token each worker holds.
- Move the ownership condition into the atomic commit. A separate read followed by a write leaves another race.
- Retest with multiple pauses, including one immediately after the ownership check would previously have passed.
Expected result: The old token fails to publish while the current owner can commit.
Verify it yourself
- Show that the fix still works if the old worker ignores cancellation.
- Keep legitimate retries from being counted as separate logical runs.
Follow-up
- Why is checking the lease only before the computation insufficient?
Suggested practice checklist
A suggested week of practice, with one concrete outcome per session. Adjust the order and pace to your experience and interview date.
Day 1 — Map your evidence
- Read your exact opening and match two responsibilities to real project examples.
Deliverable: A role-to-project map
Day 2 — Test the coding contract
- Attempt the first coding problem. Add boundary cases before reading the solution.
Deliverable: A tested function
Day 3 — Query the right record
- Run the SQL example and create a case where insertion order gives the wrong answer.
Deliverable: A small dataset and expected output
Day 4 — Trace the unhappy path
- Switch the scenario diagram and explain which state is safe to show to a reader.
Deliverable: A recovery sketch
Day 5 — Reproduce the race
- Explain the debugging example with two competing operations. Identify the atomic or identity check.
Deliverable: A reproducible timeline
Day 6 — Prepare your stories
- Choose two behavioral prompts. Use real decisions, evidence and limitations instead of memorized scripts.
Deliverable: Two concise story outlines
Day 7 — Rehearse and revise
- Explain one solution aloud, test its weakest assumption and prepare questions about the actual role.
Deliverable: A review sheet for your next session
Explain the decisions behind your work
Use a real project. Explain your responsibility, the decision you made, the evidence you used and what you would change.
- Choose examples you can discuss without sharing confidential customer data.
Explain a hypothesis you disproved
Medium · Communication · Ownership
Describe a debugging investigation in which evidence contradicted your first explanation.
Approach
- Be specific: Choose the smallest observation that changed your mind. Separate what you measured from what you inferred.
- Own your part: Distinguish your decision from the team’s work. Use a real result and state any remaining limitation.
Follow-up
- What test would have disproved the replacement hypothesis?
Defend a reliability tradeoff
Medium · Communication · Ownership
Describe a time you reduced scope to protect correctness or reproducibility.
Approach
- Be specific: Name the user impact, options rejected and follow-up that checked whether the choice worked.
- Own your part: Distinguish your decision from the team’s work. Use a real result and state any remaining limitation.
Follow-up
- What would have justified choosing speed instead?
Hand off an unresolved failure
Medium · Communication · Ownership
Explain how another engineer could continue your investigation without repeating it.
Approach
- Be specific: Provide the reproducer, known versions, attempted fixes and the next discriminating test.
- Own your part: Distinguish your decision from the team’s work. Use a real result and state any remaining limitation.
Follow-up
- What detail did you initially omit that the next person needed?