Debug and automate
Measure a transfer
Print DNS, connection, TLS, first-byte, total time, status, and downloaded size as structured evidence.
“The API is slow” is a complaint, not a diagnosis. Slow where? DNS? The TLS handshake? The server thinking? The download itself?
curl can tell you. It timestamps every stage of a transfer and exposes those numbers through --write-out variables. Measure the stages separately before you decide that a server or a network is slow.
Print a timing record
Ask for one compact line of timings:
curl --silent --output /dev/null --write-out 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first=%{time_starttransfer} total=%{time_total} code=%{response_code}\n' https://example.org/
The body goes to /dev/null. Only your formatted line prints:
dns=0.012 connect=0.048 tls=0.115 first=0.234 total=0.236 code=200
Be careful here, because this trips everyone up the first time. These values are cumulative from the start of the transfer, not per-stage durations. time_connect includes the DNS time before it. To get the cost of one stage, subtract the previous value.
In the sample above, TLS took roughly 0.115 minus 0.048, about 67 milliseconds.
The most useful gap is usually first minus tls. That’s the wait between sending the request and receiving the first response byte. It’s the server working. A big gap there, with fast numbers before it, means the network is fine and the backend is slow.
Interpret with care
Compare repeated runs. Connection reuse, DNS caching, server load, and the network path can change every stage:
for i in 1 2 3 4 5; do
curl --silent --output /dev/null --write-out 'total=%{time_total} code=%{response_code}\n' https://example.org/
done
The first run often pays for a cold DNS cache. Later runs hit a warm resolver and look faster for reasons that have nothing to do with the server.
Add %{size_download} when byte counts matter. A “fast” response that returned 87 bytes of error JSON is not a healthy response, and the status code alone can miss that.
One request is not a benchmark
Five requests from your laptop describe your laptop’s path to the server at that moment. That’s real evidence, as long as you label it as exactly that. Note the target, where you ran it from, and when.
My advice when you suspect a slow endpoint: run the loop above from your machine, then from a server in another region. If both show a big first gap, it’s the backend. If only one does, it’s the path.
Try it on your own site: run the timing line against your homepage and against an API route. The difference in first tells you how much time your code adds on top of the network.
Lesson completed