A request fails or is slow only for some users. How do you diagnose it: what do you log, what tools do you use, and what are the usual causes?
Mental model. Finding a leak in a house: check whether the water reaches the meter, then the pipe, then the tap, instead of replacing every tap.
Work from the outside in. First reproduce and classify: is it a URL or request problem (check the exact URL, headers, body; log it without secrets), a transport problem (URLError code, Q553), a server answer (status, Retry-After, a request id header you log), or a client-side decode problem? Add a request id you generate and the server echoes, so one line connects the app log, the proxy log and the backend trace. Capture timings per request with URLSessionTaskMetrics (see the metrics question below) and send them to analytics aggregated by endpoint, network type and app version, because the failing minority hides in averages.
Tools: Network Link Conditioner and the Simulator’s network settings to reproduce poor networks (latency, loss, 3G); an HTTP debugging proxy (Proxyman, Charles, mitmproxy) to read requests, with the proxy’s certificate trusted on the device (pinned apps will refuse it by design, so use a debug build flag); curl -v or nscurl --ats-diagnostics against the same URL to separate app bugs from server or ATS problems; Instruments’ Network template and the Console subsystem logs; and the CFNETWORK_DIAGNOSTICS=3 environment variable for verbose CFNetwork logging while debugging. Usual causes: expired or mis-set auth, a certificate chain or ATS issue, captive portals and corporate proxies returning HTML for your JSON, IPv6-only or DNS64 networks with hard-coded IPv4, stale connections after a network change (retry idempotent calls once), and low-quality links with a short idle timeout. Document each class of failure in a runbook so the next person recognises it.
Common traps
- Debugging only on the office Wi-Fi. Many failures need loss, latency or a proxy to appear.
- Logging full URLs and headers with tokens. Redact credentials and personal data.
They might follow up with
- How do I tell my bug from a server bug? Reproduce with
curlusing the same request; if it fails there, the server or network is the cause. - What about intermittent failures? Correlate by network type, carrier, OS version and region in your metrics before guessing.
Related questions
- 12.10.4 What does URLSessionTaskMetrics tell you about a request, and how do you use it to find where time goes?
- 12.8.3 How do you classify what URLSession reports: which failures are URLError, which are not, and which are worth…
- 12.2.2 How do TLS and App Transport Security protect a request, and what is certificate pinning, and why is it…
- 12.4.3 Why use NWPathMonitor instead of reachability, and how do you use connectivity information correctly?
- 12.6.2 How would you design a networking layer shared by many apps and teams: interceptors, mocking, and URLProtocol?
← When do you still need a URLSession delegate, and how do the async… What does URLSessionTaskMetrics tell you about a request, and how do… →