Load test "connection refused" early: target not ready in CI
The single most common CI-only load-test failure is starting the test before the target service is up. k6, Gatling, Locust, and JMeter all report connection refused when nothing is listening yet. The fix is a readiness gate, not a change to the test.
What this error means
The load run shows 100% connection refused or KO from the first request, yet the same test passes locally where the target is already running.
# k6
dial tcp 127.0.0.1:8080: connect: connection refused
# JMeter
Non HTTP response code: java.net.ConnectException: Connection refusedCommon causes
No readiness wait before the test
The pipeline launches the load tool immediately after starting the app, before it finishes binding its port.
A slow-starting dependency behind the target
The app itself waits on a database or cache; until those are ready it does not accept connections, so early requests are refused.
How to fix it
Poll the health endpoint before the load step
- Add a bounded wait loop that curls the health endpoint.
- Break out once it answers, or fail after a timeout.
- Run the load tool only after readiness is confirmed.
for i in $(seq 1 30); do
curl -sf http://localhost:8080/health && break
sleep 2
doneUse a service healthcheck as the gate
Let the CI service container expose a healthcheck so the job waits for healthy before the load step runs.
services:
app:
image: my/app
options: >-
--health-cmd "curl -sf http://localhost:8080/health"
--health-interval 5s --health-retries 10How to prevent it
- Gate every load-test step behind a target readiness check.
- Wait on the app health endpoint, not a fixed sleep.
- Expose healthchecks on service containers so CI waits for healthy.