autocannon POST: Bodies, Headers, and Gates
autocannon -m POST -b body.json -H Content-Type=application/json loads a write endpoint, and the result object exposes non2xx and latency percentiles for CI gates.
Benchmarking a POST path with autocannon needs the method, a body, and the right content type, plus a gate: the CLI exits 0 even when every request returns 500, so you assert on the reported counts.
What it does
With -m POST and -b autocannon sends the same body each request; -H k=v sets headers (note the = separator, not a colon). The final report and the programmatic result both expose 2xx, non2xx, errors, and latency percentiles, which are what you gate on.
Common usage
// bench.js - fail on p99 or any non-2xx
const autocannon = require('autocannon')
autocannon({
url: 'http://localhost:8080/api',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ k: 'v' }),
connections: 50, duration: 20,
}, (err, res) => {
if (err) throw err
if (res.non2xx > 0 || res.latency.p99 > 500) process.exit(1)
})Options
| Field | What it does |
|---|---|
| method: POST | HTTP method for every request |
| body | Request body string |
| headers | Object of request headers |
| connections / duration | Concurrency and run length (seconds) |
| res.non2xx | Count of non-2xx responses (gate on this) |
| res.latency.p99 | p99 latency in ms (gate on this) |
In CI
Prefer the programmatic form so one script both runs the load and enforces the SLO with process.exit(1). Send one warm-up request before the measured run. Remember CLI header syntax is -H name=value (equals), unlike curl-style colons, a frequent copy-paste bug.
Common errors in CI
A body that the server rejects shows up as non2xx (e.g. 400/422), not as an error, so a gate that only checks res.errors passes wrongly; check non2xx too. Cannot find module 'autocannon' in the script means it is not in the project deps; npm i -D autocannon. Using -H "Content-Type: application/json" (colon) can send a malformed header; use the = form on the CLI.