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 time is being lost outside your server: a proxy between you buffers or drops the response, their client isn't reading it (streaming misuse), or the request waited in their connection pool before it was ever sent, so their clock started long before yours.
- 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 suggests where to investigate next. The timings alone do not assign fault:
| 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 | Connection establishment: network filtering, NAT, or an egress proxy refusing the connection |
dns/conn/tls fine, first-byte slow | Request and response transit, a proxy, or server work; compare server timing for the same request ID |
| Everything fast in curl, app still times out | Suspect connection-pool exhaustion or event-loop starvation; first check that the probe uses the same endpoint and route |
The last row is the subtle one: repeated clean curls from their environment during a failure window strengthen the case for a client-runtime problem when the endpoint and route match. One clean probe proves little against an intermittent fault, and even repeated probes may miss an app-specific connection problem. Ask "how big is your HTTP connection pool, and what is your concurrency?" before assigning an owner.
That separates connection setup, the wait for a response, and transfer without touching their code. For this single HTTPS request, curl reports each time cumulatively from the start, so read the jumps between consecutive values; first-byte minus tls is the post-handshake wait for the first byte (request transit, any proxy in the path, server work and the first byte's return, so correlate it with your server-side timing for the same request ID before calling it think time), and conn minus dns is the TCP handshake. A stale keep-alive socket is a different case: the app reuses an existing connection, which this fresh curl connection may not reproduce.
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.
