Healthchecks
For each app port WorktreeOS runs an HTTP healthcheck after the services start
successfully, and only completes wos up once every required healthcheck
has passed. This applies to the Docker-backed generated and compose modes and to
shell mode alike — in shell mode the check polls
the host port the service process binds.
How the check runs
Section titled “How the check runs”wos up polls the port repeatedly within the overall timeout window
(default 3m). Errors during start_period (default 15s) are not counted
against retries; WorktreeOS then waits interval (default 5s) between
attempts and ends the check after retries failed attempts (default 20) or
once timeout elapses.
While the check is in progress the status reads waiting (yellow); if it ends
without a successful response, it reads FAILED.
The lenient default
Section titled “The lenient default”By default any HTTP response below 500 (200, 204, 301/302, 401/403/404, …) is treated as success — it means the service is accepting connections. 5xx codes and network errors are failures.
The numeric port notation is equivalent to an object with default values:
healthcheck: { url: "/" } plus timeouts from the global settings, and
allow_failure: false.
Per-port options
Section titled “Per-port options”The full set of fields is
healthcheck: { url, status, timeout, start_period, interval, retries }:
urlmust start with/.statusis within100..599. Addingstatus: Nmakes the check strict (e.g.status: 204accepts only204).- durations accept a number of milliseconds or strings with
ms,s,msuffixes;retriesis a positive integer.
Special values:
healthcheck: false— disable the check for that port.allow_failure: true— a failing check does not abortwos up; it appears in status as failed (allowed).
app: services: api: ports: - 3000 # default healthcheck GET / -> < 500 - port: 3002 healthcheck: url: /health status: 204 timeout: 1m start_period: 10s interval: 10s retries: 3 - port: 4000 healthcheck: false # port without a check - port: 5000 allow_failure: true # a failed check does not abort upTiming parameters not provided per port fall back to the healthcheck block in
<wos-home>/config.json, and if absent there too, to the built-in defaults.
Global defaults
Section titled “Global defaults”To change timings for every service in the project (or across projects) without
editing the deploy config, add a healthcheck section to
<wos-home>/config.json:
{ "healthcheck": { "timeout": "5m", // a string with ms|s|m suffix or a number of ms "start_period": "30s", "interval": "5s", "retries": 30, "request_timeout": "15s" // how long to wait for a single HTTP response }}request_timeout is the limit for an individual HTTP call within the waiting
window (default 10s). If a service warms up slowly (Spring, Rails, an ML
server) and the first request to / takes longer than 10 seconds, healthchecks
keep failing on per-attempt timeout even with a live container — increase
request_timeout.
Any field explicitly set in the deploy config (including numeric per-port values)
takes precedence over the global config.json. Changes take effect after a daemon
restart (wos restart).
Status values
Section titled “Status values”wos status reports each port’s healthcheck as one of:
healthy— the configured URL returned the expected status in time.waiting— still polling withinstart_period/timeout/retries.failed— the budget expired without a healthy response andallow_failureis false.failed (allowed)— failed, but the port hasallow_failure: true.disabled— the port hashealthcheck: false.
See Healthcheck failures for debugging.