Reproduce an API Timeout with curl Trace
Break a slow API call into DNS, connect, TLS, and first-byte timings so you can prove which phase consumes the latency budget.
Task
Measure each phase of a slow request with curl write-out variables and attribute the delay to a specific network or server phase.
When to use this
Users report an eight-second delay intermittently, but server metrics show fast handler times, suggesting the delay is in connection setup.
Prerequisites
- curl 8.x with timing write-out support
- A staging host replicating production DNS and TLS
- A repeatable request that occasionally runs slow
Steps
1. Capture per-phase timings with a single request.
curl -o /dev/null -s -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
https://api.example.com/v1/search?q=testExpected output: Each phase is printed, so a slow time_namelookup indicates DNS rather than the server.
2. Repeat in a loop to expose variance and outliers.
for i in $(seq 1 20); do
curl -o /dev/null -s -w '%{time_namelookup} %{time_connect} %{time_total}\n' https://api.example.com/health
done | sort -k3 -n | tail -3Expected output: The three slowest runs show whether variance is in DNS, connect, or total time.
Troubleshooting
Problem
time_namelookup is noisy
Solution
Compare against a fixed IP to separate resolver latency from connection latency.
Problem
Slow only from one region
Solution
Run the same trace from that region and compare the connect phase across regions.
Limitations
- Client-side timing includes the local network, not just the server.
- Does not inspect TLS CPU cost beyond handshake duration.
- A single run is not evidence; always sample repeatedly.
What this recipe does
Measure each phase of a slow request with curl write-out variables and attribute the delay to a specific network or server phase.
Users report an eight-second delay intermittently, but server metrics show fast handler times, suggesting the delay is in connection setup.
Prerequisites
- curl 8.x with timing write-out support
- A staging host replicating production DNS and TLS
- A repeatable request that occasionally runs slow
Procedure
- Capture per-phase timings with a single request.
curl -o /dev/null -s -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
https://api.example.com/v1/search?q=test
Expected result: Each phase is printed, so a slow time_namelookup indicates DNS rather than the server.
- Repeat in a loop to expose variance and outliers.
for i in $(seq 1 20); do
curl -o /dev/null -s -w '%{time_namelookup} %{time_connect} %{time_total}\n' https://api.example.com/health
done | sort -k3 -n | tail -3
Expected result: The three slowest runs show whether variance is in DNS, connect, or total time.
How to confirm it worked
Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows the per-phase output consistently shows one dominant phase, and a fix to that phase lowers total time in the repeated run.
Troubleshooting
time_namelookup is noisy — Compare against a fixed IP to separate resolver latency from connection latency.
Slow only from one region — Run the same trace from that region and compare the connect phase across regions.
Limitations
- Client-side timing includes the local network, not just the server.
- Does not inspect TLS CPU cost beyond handshake duration.
- A single run is not evidence; always sample repeatedly.