Apache ab Benchmark
Basic Usage
# Install
# macOS: brew install httpd (or already installed with Xcode tools)
# Debian/Ubuntu: sudo apt install apache2-utils
# CentOS/RHEL: sudo yum install httpd-tools
# Basic GET benchmark
ab -n 1000 -c 10 https://example.com/
# Flags:
# -n total number of requests
# -c concurrent requests (users)
# -t time limit in seconds (instead of -n)
# Simple examples
ab -n 500 -c 5 http://localhost:3000/api/health
ab -n 5000 -c 100 https://api.example.com/users
ab -t 30 -c 50 http://localhost:8080/ # run for 30 seconds
# HTTPS with SSL verification disabled
ab -n 1000 -c 20 -k https://example.com/
POST Requests & Headers
# POST with JSON body
# Create body file first:
# echo '{"username":"test","password":"pass"}' > body.json
ab -n 500 -c 10 \
-p body.json \
-T application/json \
http://localhost:3000/api/login
# POST with form data
# echo "username=test&password=pass" > form.txt
ab -n 1000 -c 20 \
-p form.txt \
-T application/x-www-form-urlencoded \
http://localhost:3000/login
# Custom headers
ab -n 1000 -c 10 \
-H "Authorization: Bearer mytoken123" \
-H "Accept: application/json" \
-H "X-Custom-Header: value" \
http://localhost:3000/api/users
# With cookies
ab -n 500 -c 10 \
-C "sessionid=abc123; csrftoken=xyz" \
http://localhost:3000/dashboard
KeepAlive & HTTP Version
# Enable HTTP KeepAlive (persistent connections)
ab -n 5000 -c 100 -k http://localhost:3000/
# HTTP/1.0 (default)
ab -n 1000 -c 10 -0 http://localhost:3000/
# Timeout per request (seconds)
ab -n 1000 -c 50 -s 30 http://localhost:3000/api/heavy
# Disable non-2xx failures (count redirects as success)
# Note: ab doesn't follow redirects by default
# Verbose output
ab -n 100 -c 5 -v 2 http://localhost:3000/
# SSL options
ab -n 1000 -c 20 \
-z TLSv1.2 \
https://example.com/
Output Export
# Export to gnuplot data file
ab -n 5000 -c 50 -g results.tsv http://localhost:3000/
# Export HTML report
ab -n 5000 -c 50 -w http://localhost:3000/ > report.html
# Pipe to file
ab -n 1000 -c 20 http://localhost:3000/ | tee ab-results.txt
# Multiple runs (compare before/after)
ab -n 2000 -c 20 http://localhost:3000/before > before.txt
# (make changes)
ab -n 2000 -c 20 http://localhost:3000/after > after.txt
diff before.txt after.txt
Interpreting ab Output
Server Software: nginx/1.24.0
Server Hostname: localhost
Server Port: 3000
Concurrency Level: 50
Time taken for tests: 12.345 seconds
Complete requests: 5000
Failed requests: 0 ← 0 is ideal
Non-2xx responses: 0
Requests per second: 405.04 [#/sec] ← throughput
Time per request: 123.45 [ms] (mean, across all concurrent)
Transfer rate: 312.50 [Kbytes/sec]
Connection Times (ms):
min mean[+/-sd] median max
Connect: 0 1 0.5 1 5
Processing: 45 119 32.1 115 456
Waiting: 42 115 31.8 111 452
Total: 45 120 32.3 116 460
Percentage of the requests served within a certain time (ms)
50% 116 ← median (P50)
66% 128
75% 138
80% 143
90% 162 ← P90
95% 180 ← P95
98% 200
99% 215 ← P99
100% 460 ← slowest request (max)
Flag Quick Reference
| Flag | Description | Example |
|---|---|---|
-n | Total requests | -n 1000 |
-c | Concurrent users | -c 50 |
-t | Time limit (seconds) | -t 30 |
-k | Enable KeepAlive | -k |
-p | POST body file | -p body.json |
-T | Content-Type header | -T application/json |
-H | Extra request header | -H "Auth: Bearer token" |
-C | Cookie | -C "sid=abc" |
-g | Gnuplot data output | -g out.tsv |
-s | Request timeout (s) | -s 30 |