TL;DR: Split the problem at the API boundary using your own request-ID logs, which yields three mutually exclusive outcomes (arrived-fast, arrived-slow, never-arrived), each with a different fix. That converts a blame conversation into a data conversation and keeps the relationship intact.
How to approach it
This is the canonical FDE triage genre: debugging across a trust boundary with partial visibility. The method interviewers want is (1) characterize the failure precisely, (2) split the problem at the API boundary using your own telemetry, (3) instrument the gap cooperatively, (4) know the classic client-side culprits without ever blaming the customer. Tone matters: you're scored on partnership, not just diagnosis.
A strong answer
Characterize first. "Intermittent" is not a symptom; pin it down. What percentage of calls? Clustered by time of day, payload size, endpoint, or concurrency? What timeout are they hitting, their client-side limit (after how many seconds?) or a 504 from your edge? Did it ever work, and what changed around onset? Ask them for timestamps and request IDs of five failures, because concrete artifacts beat adjectives.
Split at the boundary. Pull your own logs for those request IDs. Three mutually exclusive outcomes, each with a different next move:
- Requests arrived and completed fast on your side, so the response isn't making it back or their client gives up: their timeout is shorter than your processing time, a proxy between you buffers, or they're not reading the response (streaming misuse).
- Requests arrived and were slow, so it's yours: check whether those requests share a tenant, payload shape, or backend path; correlate with your p99 and capacity.
- Requests never arrived, so it's network or client: DNS, connection establishment, their egress proxy or firewall, connection-pool exhaustion on their side.
The split converts a blame conversation into a data conversation.
Instrument the gap. If logs don't settle it, get a minimal repro outside their app: curl with timing breakdown from their environment, run on a cron during the failure window. The exact command is worth having memorized, because dictating it over a screen-share is a moment that builds enormous credibility:
curl -s -o /dev/null -w \
"dns %{time_namelookup} conn %{time_connect} tls %{time_appconnect} \
first-byte %{time_starttransfer} total %{time_total}\n" \
https://api.example.com/v1/health
Each failing sample then reads as a signature, and the signatures map to owners:
| Timing pattern in the bad samples | Points at |
|---|---|
dns spikes to seconds, rest normal | Their resolver or DNS path; often one flaky resolver in a rotation |
conn hangs or times out, dns fine | Firewall, NAT idle-killed keep-alive, egress proxy refusing the connection |
dns/conn/tls fine, first-byte slow | Your side: the server genuinely thought for that long; correlate with case 2 |
| Everything fast in curl, app still times out | Inside their process: connection-pool exhaustion or event-loop starvation, the culprit curl can never see |
The last row is the subtle one: a clean curl during a failure window is itself strong evidence, because it exonerates the network path end to end and narrows the search to the one place you cannot instrument, their client runtime, which is exactly the conversation ("how big is your HTTP connection pool, and what is your concurrency?") that cracks most of these cases.
That isolates DNS vs TLS vs server-think-time vs transfer without touching their code.
Know the classic culprits. Intermittent timeouts from an opaque client are usually one of: client connection-pool exhaustion under concurrency (calls queue locally, then time out, which looks identical to a slow server from inside their app); stale keep-alive connections killed by a NAT or firewall idle timeout, where the next request on a dead socket hangs; DNS flakiness or rotating resolution to a bad path; their egress proxy (corporate environments especially) with its own timeout and buffering behavior; or missing retries with the wrong timeout budget, for example their 10s client timeout against your legitimate p99 of 12s on large payloads.
Offer fixes on your side regardless of fault: request IDs in every response, a status and latency dashboard they can see, documented timeout-and-retry guidance (timeout greater than your p99, exponential backoff with jitter, idempotency keys so retries are safe).
What interviewers probe next
- "Your logs show nothing, the request never arrived. They insist they sent it." Run tcpdump or packet capture on their egress, check their proxy logs, compare DNS resolution from their network versus yours.
- "How do you handle the customer's engineer getting defensive?" Frame everything as "let's instrument the boundary," never "your code is wrong"; share your evidence first to model transparency.
- "What would you build so the next customer doesn't need you?" Self-serve request-ID lookup, client libraries with sane defaults, a troubleshooting runbook.
Common mistakes
Guessing causes before characterizing the failure pattern. Treating "we can't see their code" as a dead end instead of a constraint to engineer around. Jumping to "it's their network" without evidence: even when true, asserting it without data torches the relationship. Forgetting your own side could be guilty (case 2). And never producing the boundary-split structure, the actual rubric item for this genre.
Key takeaways
- Characterize before guessing: percentage, clustering, which timeout, what changed at onset.
- The boundary split has three outcomes (arrived-fast, arrived-slow, never-arrived); each points to a different owner.
- Client connection-pool exhaustion looks identical to a slow server from inside their app; do not misread it.
- Never assert "it's your network" without evidence; share your request-ID data first.
