Customer Bootstrap API
Reported by candidates from DoorDash's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
DoorDash reported this one in September 2026, and it looks like a system design question but it's a plain simulation. The mistake that sinks a first attempt is treating a slow 200 as a success. You get a status of 200 with latency over the timeout, and it has to count as retryable, not as the answer. Three services, a retry loop, and a few rules about what stops the loop. If you blank on the edge cases during the OA, StealthCoder is the safety net running invisibly on your screen. Read the rules slowly and the code is short.
The problem
Implement a deterministic customer-bootstrap endpoint that orchestrates three downstream services. First resolve an email address through USER to obtain a customer identifier. After that succeeds, resolve PAYMENT and ADDRESS independently; these two lookups are logically concurrent. The input response schedule contains rows [service, attempt, latencyMs, statusCode, value]. The service is USER, PAYMENT, or ADDRESS. A missing row represents a timeout. For each service, inspect attempts from 1 through maxAttempts: A response succeeds when its latency is at most timeoutMs and its status is 200. Return its value. A response with latency greater than timeoutMs, a missing response, or status 500 through 599 is retryable. Any other status is terminal for that service. If USER does not succeed, return three empty strings. Otherwise return [customerId, defaultCard, address]. A failed PAYMENT lookup contributes UNKNOWN_CARD; a failed ADDRESS lookup contributes UNKNOWN_ADDRESS. The independent downstream lookup may succeed even when the other one fails. Function bootstrapCustomer(email: String, timeoutMs: int, maxAttempts: int, responses: String[][]) → String[] Examples Example 1 email = "alex@example.com" timeoutMs = 100 maxAttempts = 2 responses = [["USER","1","20","200","c42"],["PAYMENT","1","150","200","card-old"],["PAYMENT","2","40","200","card-7"],["ADDRESS","1","30","503",""],["ADDRESS","2","25","200","12 Main St"]] return = ["c42","card-7","12 Main St"] The user lookup succeeds immediately. The first payment response exceeds the timeout and the first address response is retryable, so both downstream services succeed on attempt 2. Constraints 1 <= email.length <= 254 1 <= timeoutMs <= 60000 1 <= maxAttempts <= 10 0 <= responses.length <= 30 Every row has exactly five fields and names one of the three services. Each service has at most one row for a given attempt number; attempt numbers are in [1, maxAttempts]. Latency and status fields are decimal integers. Latency is nonnegative. Values contain at most 200 visible ASCII characters.
Reported by candidates. Source: FastPrep
Pattern and pitfall
Write one helper: resolve(service) that loops attempts 1 through maxAttempts, finds the row for that service and attempt, and applies the rules in order. Missing row means retry. Latency over timeoutMs means retry, even with status 200. Otherwise status 200 returns the value. Status 500-599 means retry. Any other status is terminal, so break and fail immediately. That terminal case is the common pitfall, since people keep retrying on a 404. Index the rows in a hash map keyed by service plus attempt for quick lookup. Then call USER first. If it fails, return three empty strings. Otherwise call PAYMENT and ADDRESS separately, substituting UNKNOWN_CARD and UNKNOWN_ADDRESS on failure. No real concurrency is needed, since the schedule is deterministic. If the live OA has you second-guessing the order of checks, StealthCoder is the hedge that reads the prompt and gives you the loop.
StealthCoder is the hedge for the one pattern you didn't drill. It runs invisibly during the screen share.
You can drill Customer Bootstrap API cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. If you're reading this with an OA window open, you're who this was built for.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass DoorDash's OA.
DoorDash reuses patterns across OAs. If you're reading this with an OA window open, you're who this was built for. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Customer Bootstrap API FAQ
How hard is the DoorDash Customer Bootstrap API question really?+
Easy on algorithms, annoying on details. There's no clever data structure. The difficulty is applying the retry rules in the right order and not skipping the terminal status case. A clean helper function makes it about 30 lines.
What's the trick to this problem?+
Write one resolve function and reuse it for all three services. Check timeout first, then status 200, then 5xx retry, then everything else as terminal. Calling it three times keeps the logic identical and avoids copy-paste bugs.
Do I need real concurrency for PAYMENT and ADDRESS?+
No. The responses are a fixed schedule, so the result is deterministic. Call the two lookups one after the other. Just make sure one failing doesn't stop the other from returning its value.
What edge cases should I test before submitting?+
Test a 200 response with latency above timeoutMs, a 404 on attempt 1 with a valid attempt 2 (must stay failed), an empty responses array, and USER failing while the other services have good rows. That last one must still return three empty strings.
How do I prepare for this in 48 hours?+
Practice simulation problems with retry or state rules. Read the spec once, write the rule order as comments, then code it. Build a lookup map from service and attempt to row, and hand-trace Example 1 before you run anything.