Hey Cheat Sheet
Overview
Hey is a small, portable HTTP load generator written in Go, originally forked from the discontinued boom project. It sends a configurable number of requests to a URL and reports latency distribution, throughput, and status code breakdown. Hey is designed for quick benchmarks rather than complex scenario-based load tests.
Hey supports HTTP/1.1 and HTTP/2, custom headers, request bodies, client certificates, and proxy configuration. Its simplicity makes it ideal for quick ad-hoc performance checks during development or as part of CI pipelines where a lightweight tool is preferred over heavier frameworks.
Installation
# macOS via Homebrew
brew install hey
# Go install
go install github.com/rakyll/hey@latest
# Linux - download binary
curl -L https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64 -o hey
chmod +x hey
sudo mv hey /usr/local/bin/
# Verify installation
hey --help
Core Commands
| Flag | Description |
|---|---|
-n | Total number of requests (default: 200) |
-c | Number of concurrent workers (default: 50) |
-z | Duration of test (e.g., 10s, 1m) |
-q | Rate limit per worker (QPS) |
-m | HTTP method (default: GET) |
-H | Custom header (repeatable) |
-d | Request body string |
-D | Request body file path |
-T | Content-Type header |
-t | Timeout per request in seconds (default: 20) |
-o | Output format: csv, json |
-h2 | Enable HTTP/2 |
-disable-compression | Disable compression |
-disable-keepalive | Disable HTTP keep-alive |
-disable-redirects | Disable following redirects |
-host | Override Host header |
-cpus | Number of CPUs to use |
Basic Usage
# Send 1000 requests with 10 concurrent workers
hey -n 1000 -c 10 https://api.example.com/health
# Run for 30 seconds with 50 concurrent workers
hey -z 30s -c 50 https://api.example.com/
# Rate-limited: 10 requests/sec per worker, 5 workers = 50 QPS total
hey -z 60s -c 5 -q 10 https://api.example.com/
# POST request with JSON body
hey -n 500 -c 20 -m POST \
-H "Content-Type: application/json" \
-d '{"name":"test","value":42}' \
https://api.example.com/data
# POST with body from file
hey -n 500 -c 20 -m POST \
-T "application/json" \
-D payload.json \
https://api.example.com/data
Custom Headers and Authentication
# Bearer token authentication
hey -n 200 -c 10 \
-H "Authorization: Bearer eyJhbGciOi..." \
https://api.example.com/protected
# Multiple custom headers
hey -n 200 -c 10 \
-H "Authorization: Bearer token123" \
-H "X-Request-ID: load-test" \
-H "Accept: application/json" \
https://api.example.com/users
# Basic auth via header
hey -n 100 -c 5 \
-H "Authorization: Basic dXNlcjpwYXNz" \
https://api.example.com/admin
Output Formats
# Default human-readable output
hey -n 1000 -c 50 https://api.example.com/
# CSV output for spreadsheet analysis
hey -n 1000 -c 50 -o csv https://api.example.com/ > results.csv
# JSON output for programmatic processing
hey -n 1000 -c 50 -o json https://api.example.com/ > results.json
Sample Default Output
Summary:
Total: 5.2381 secs
Slowest: 0.4523 secs
Fastest: 0.0012 secs
Average: 0.0245 secs
Requests/sec: 190.9102
Response time histogram:
0.001 [1] |
0.046 [923] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.091 [52] |■■
0.136 [14] |■
0.182 [5] |
0.227 [2] |
0.272 [1] |
0.362 [1] |
0.452 [1] |
Latency distribution:
10% in 0.0089 secs
25% in 0.0134 secs
50% in 0.0201 secs
75% in 0.0298 secs
90% in 0.0456 secs
95% in 0.0678 secs
99% in 0.1345 secs
Status code distribution:
[200] 998 responses
[503] 2 responses
Advanced Usage
HTTP/2 Testing
# Force HTTP/2
hey -n 500 -c 20 -h2 https://api.example.com/
# Compare HTTP/1.1 vs HTTP/2
echo "--- HTTP/1.1 ---"
hey -n 1000 -c 50 https://api.example.com/
echo "--- HTTP/2 ---"
hey -n 1000 -c 50 -h2 https://api.example.com/
Connection Behavior Testing
# Test without keep-alive (new connection per request)
hey -n 500 -c 10 -disable-keepalive https://api.example.com/
# Test without compression
hey -n 500 -c 10 -disable-compression https://api.example.com/
# Test without following redirects
hey -n 500 -c 10 -disable-redirects https://api.example.com/old-endpoint
TLS Client Certificates
# Mutual TLS testing
hey -n 200 -c 10 \
-cert client.crt \
-key client.key \
https://secure.example.com/api
Proxy Configuration
# HTTP proxy
hey -n 200 -c 10 -x http://proxy.example.com:8080 https://api.example.com/
# Environment variable proxy
export HTTP_PROXY=http://proxy.example.com:8080
hey -n 200 -c 10 https://api.example.com/
Scripted Benchmarking
#!/bin/bash
# Benchmark script comparing different concurrency levels
URL="https://api.example.com/endpoint"
for c in 1 5 10 25 50 100; do
echo "=== Concurrency: $c ==="
hey -n 1000 -c $c -o json "$URL" | \
jq '{concurrency: .concurrency, rps: .rps, avg_latency: .average, p99: .latencyDistribution[-1].latency}'
echo ""
done
Configuration
# Set CPU count for multi-core usage
hey -cpus 4 -n 10000 -c 100 https://api.example.com/
# Custom timeout for slow endpoints
hey -t 60 -n 100 -c 5 https://api.example.com/slow-endpoint
# Override Host header for virtual hosting
hey -n 200 -c 10 -host "api.example.com" https://10.0.0.1/health
Troubleshooting
| Issue | Solution |
|---|---|
too many open files | Increase ulimit: ulimit -n 10240 |
| All requests fail | Check URL accessibility, firewall, DNS resolution |
| Timeouts on all requests | Increase -t timeout value |
| Low throughput numbers | Ensure test machine is not the bottleneck; check network |
| Results vary wildly | Run multiple iterations and average; check for background load |
connection reset by peer | Server may be rate-limiting; reduce -c concurrency |
| HTTP/2 errors | Verify server supports HTTP/2; try without -h2 |
| Proxy not working | Check proxy URL format and reachability |