Skip to content
Latchkey

ab -k -p: POST Bodies and KeepAlive

ab -p body.json -T application/json POSTs a fixed body on every request, and -k reuses connections with HTTP KeepAlive.

ApacheBench defaults to GET and one connection per request. For a realistic write path you need -p (a body file) with -T (its content type), and -k to stop paying a TCP handshake on every call.

What it does

With -p <file> ab switches to POST and sends the file contents as the request body on every request; -T sets the Content-Type header (there is no default, so it must be given). -k turns on KeepAlive so connections are reused, which changes both throughput and the connection-error profile. Use -u <file> for PUT.

Common usage

Terminal
printf '{"name":"ci-run"}' > body.json
ab -n 5000 -c 50 -k \
  -p body.json -T 'application/json' \
  -H 'Authorization: Bearer test' \
  http://localhost:8080/api/items

Options

FlagWhat it does
-p <file>POST the file contents as the body
-u <file>PUT the file contents instead
-T <type>Content-Type for -p/-u (required with them)
-kEnable HTTP KeepAlive (reuse connections)
-H <header>Extra request header (repeatable)
-C <name=value>Add a Cookie header

In CI

Warm the endpoint with one request before the measured run so JIT/connection-pool cold start does not skew the first percentiles. Then gate on Non-2xx responses: being zero (a 401/422 from a bad payload will otherwise pass silently since ab still exits 0).

Common errors in CI

Forgetting -T with -p makes the server reject the body or misparse it, showing up as Non-2xx responses. ab: Could not open POST data file means a wrong path to the body file. If KeepAlive shows Keep-Alive requests: 0, the server closed each connection (often a missing Connection: keep-alive on its side), so -k gave no benefit.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →