locust --headless: Run Load Tests in CI
locust --headless -u 100 -r 10 --run-time 2m runs a locustfile.py load test with 100 users ramped at 10/s for two minutes, no browser UI, and can exit non-zero on failure.
Locust defines load in Python (a locustfile with HttpUser tasks). For CI you run it headless with a fixed user count, spawn rate, and run time, and use its check flags so a bad p95 or RPS fails the build.
What it does
locust runs the tasks in locustfile.py. --headless skips the web UI and starts immediately; -u sets peak users, -r the spawn rate, and --run-time the duration. It prints an aggregated stats table (requests, failures, median, p95, RPS) and, with --exit-code-on-error or check thresholds, returns non-zero.
Common usage
locust -f locustfile.py --headless \
-u 100 -r 10 --run-time 2m \
--host http://localhost:8080 \
--csv results \
--exit-code-on-error 1Options
| Flag | What it does |
|---|---|
| --headless | Run without the web UI, start at once |
| -u, --users N | Peak number of concurrent users |
| -r, --spawn-rate N | Users started per second |
| --run-time T | Stop after this long, e.g. 2m, 30s |
| --host <url> | Base host if not set in the locustfile |
| --csv <prefix> | Write stats CSVs for later parsing |
| --exit-code-on-error N | Exit code when any request failed |
In CI
Combine --run-time (so headless mode terminates instead of running forever) with a gate. The cleanest gate is a @events.quitting listener in the locustfile that sets environment.process_exit_code = 1 when stats.total.get_response_time_percentile(0.95) exceeds budget or total RPS is too low. --exit-code-on-error 1 only covers request failures, not slow-but-successful responses.
Common errors in CI
locust: command not found means the venv is not installed or activated; pip install locust. Could not find any locustfile means a wrong -f path or filename. A headless run that never ends means you forgot --run-time. ConnectionRefusedError on the first requests means the --host is not accepting connections yet; add a readiness wait.