hey: Quick HTTP Load Testing in CI
hey -n <requests> -c <concurrency> <url> fires HTTP requests at a target and reports latency percentiles and a status-code breakdown.
hey (the successor to ApacheBench) is a single binary that sends a fixed number of requests at a chosen concurrency, making it a fast smoke load test for a CI job.
What it does
hey issues -n total requests with -c running concurrently (or runs for a duration with -z), then prints a latency histogram, percentile breakdown, requests per second, and a status-code distribution. It does not parse response bodies.
Common usage
hey -n 2000 -c 50 https://staging.example.com/
# run for a fixed duration instead of a count
hey -z 30s -c 100 https://staging.example.com/api/health
# POST with a header and body
hey -m POST -H "Authorization: Bearer $TOKEN" \
-d '{"ping":true}' https://staging.example.com/apiOptions
| Flag | What it does |
|---|---|
| -n <num> | Total number of requests |
| -c <num> | Number of concurrent workers |
| -z <dur> | Run for a duration (e.g. 30s) instead of -n |
| -m <method> | HTTP method (GET default) |
| -H "K: V" | Add a header (repeatable) |
| -d <body> / -D <file> | Request body inline or from a file |
In CI
hey does not fail on slow responses, so capture its output and grep the status-code section: if any non-2xx appears, fail the step. Pass tokens with -H "Authorization: Bearer $TOKEN" from a CI secret rather than hardcoding them.
Common errors in CI
"Get \"...\": dial tcp: connect: connection refused" means the target is not up yet; wait for the service before running hey. A summary where "Status code distribution" shows only [0] responses means every request errored (DNS, TLS, or refused). On TLS to a self-signed staging cert, hey reports x509 errors; it has no insecure flag, so trust the cert or test plain HTTP.