wait-on: Block Until a Server Is Ready
wait-on polls a resource (http://, tcp:, or a file) and exits 0 once it is available or non-zero when the timeout passes.
Starting a web server in the background and immediately running tests is a classic race. wait-on removes it by blocking until the server actually answers.
What it does
wait-on takes one or more resources and polls them until each is available, then exits 0. For an http:// or https:// resource it waits for a non-error HTTP response; for tcp: it waits for the port to accept a connection; for a file path it waits for the file to exist. If the timeout (-t) elapses first, it exits non-zero.
Common usage
# wait for an HTTP endpoint, up to 30s
npx wait-on -t 30000 http://localhost:8080/health
# wait for a raw TCP port
npx wait-on -t 30000 tcp:localhost:5432
# start server, wait, then test
node server.js & npx wait-on http://localhost:3000 && npm testOptions
| Flag / Resource | What it does |
|---|---|
| http://host:port/path | Wait for a successful HTTP response |
| https-get://... | Wait via GET, ignoring HEAD-only endpoints |
| tcp:host:port | Wait for the TCP port to accept connections |
| -t <ms> | Overall timeout in milliseconds |
| -i <ms> | Polling interval in milliseconds |
| -r | Reverse: wait for the resource to become unavailable |
In CI
Chain server & wait-on ... && test so the tests only run once the server responds, replacing brittle sleep calls. Use an http:// resource against the real health path rather than tcp: when possible, since a bound port does not always mean the app is ready to serve. Set -t generously for cold-start on shared runners.
Common errors in CI
A non-zero exit after the timeout means the resource never became available in time; raise -t or check the server actually started. "Error: Invalid protocol" means a malformed resource string (use http:// or tcp: prefixes). If wait-on passes but the first request still fails, the endpoint returned a non-error status before the app was truly ready; wait on a deeper health path.