← Recipes

阅读中文版本

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.

~25 minhttpperformancedebugging

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=test

Expected 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 -3

Expected 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

  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=test

Expected result: Each phase is printed, so a slow time_namelookup indicates DNS rather than the server.

  1. 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.