Here are fast, reliable ways to measure client-side API response time (and break it down) — from your laptop or from an EKS pod.
1) One-shot timing (curl)
This prints DNS, TCP, TLS, TTFB, and Total in one go:
curl -s -o /dev/null -w '
{ "http_code":%{http_code},
"remote_ip":"%{remote_ip}",
"dns":%{time_namelookup},
"tcp":%{time_connect},
"tls":%{time_appconnect},
"ttfb":%{time_starttransfer},
"total":%{time_total},
"size":%{size_download},
"speed":%{speed_download}
}
' https://api.example.com/path
Fields
dns: DNS lookuptcp: TCP connecttls: TLS handshake (0 if HTTP)ttfb: time to first byte (request→first response byte)total: full download time
2) From EKS (ephemeral pod)
Run N samples and capture a CSV:
kubectl run curl --rm -it --image=curlimages/curl:8.8.0 -- \
sh -c 'for i in $(seq 1 50); do \
curl -s -o /dev/null -w "%{time_namelookup},%{time_connect},%{time_appconnect},%{time_starttransfer},%{time_total}\n" \
https://api.example.com/health; \
done' > timings.csv
Open timings.csv and look at columns: dns,tcp,tls,ttfb,total. Large ttfb means slow upstream/app; big tls means handshake issues; big gap total - ttfb means payload/download time.
3) Separate proxy vs upstream (Kong in the path)
Kong adds latency headers you can read on the client:
curl -i https://api.example.com/path | sed -n 's/^\(x-kong-.*latency\): \(.*\)$/\1: \2/p'
# x-kong-proxy-latency: <ms> (Kong → upstream start)
# x-kong-upstream-latency: <ms> (Upstream processing)
These help you see if delay is at the gateway or in the service.
4) Quick load/percentiles (pick one)
- hey
hey -z 30s -c 20 https://api.example.com/path - vegeta
echo "GET https://api.example.com/path" | vegeta attack -rate=20 -duration=30s | vegeta report - k6 (scriptable)
// save as test.js import http from 'k6/http'; import { check } from 'k6'; export const options = { vus: 20, duration: '30s', thresholds: { http_req_duration: ['p(95)<300'] } }; export default () => { const r = http.get('https://api.example.com/path'); check(r, { '200': (res)=>res.status===200 }); };Run:k6 run test.js
5) App-level timers (optional)
Add a Server-Timing header from the API to expose your own phase timings (DB, cache, etc.). Then the client can read those headers to correlate.
6) Common gotchas
- Proxies can add latency; test both with and without proxy (
NO_PROXY/--proxy). - Auth: measure with real headers/tokens; 401/403 will skew.
- SNI/Host: if hitting by IP, use
--resolve host:443:IP -H "Host: host"so cert/routing is correct. - Warmup: discard first few samples (JIT, caches, TLS session reuse).
If you want, share a few curl -w outputs from local vs EKS and I’ll pinpoint where the time is going (DNS/TLS/TTFB/payload).