# Reference: controller.yaml

URL: https://scalws.com/docs/reference/controller/
Source: `docs/reference/schema` in the ScalWS repository

<h3 id="autoscaling"><code>autoscaling</code></h3>

| | |
|---|---|
| Syntax | `autoscaling: {...}` |
| Default | `none` |
| Context | `controller.yaml` |
| Reload | applies on reload |

When the controller adds or removes instances (ADR-0034).


<h3 id="autoscaling.applications"><code>autoscaling.applications</code></h3>

| | |
|---|---|
| Syntax | `applications: [{...}, ...]` |
| Default | `none` |
| Context | `autoscaling` |
| Reload | applies on reload |

Application processes to watch (application-tier classification).


<h3 id="autoscaling.applications-.comm"><code>autoscaling.applications[].comm</code></h3>

| | |
|---|---|
| Syntax | `comm: <string>` |
| Default | `required` |
| Context | `autoscaling.applications[]` |
| Reload | applies on reload |

Process name prefix (`/proc/<pid>/comm`), e.g. `php-fpm8.3`, `node`, `uvicorn`.


<h3 id="autoscaling.applications-.cpus"><code>autoscaling.applications[].cpus</code></h3>

| | |
|---|---|
| Syntax | `cpus: <number>` |
| Default | `required` |
| Context | `autoscaling.applications[]` |
| Reload | applies on reload |

CPUs allotted to it (saturated at 90 %).


<h3 id="autoscaling.applications-.kind"><code>autoscaling.applications[].kind</code></h3>

| | |
|---|---|
| Syntax | `kind: <string>` |
| Default | `required` |
| Context | `autoscaling.applications[]` |
| Reload | applies on reload |

`php`, `node` or `python`.


<h3 id="autoscaling.applications-.name"><code>autoscaling.applications[].name</code></h3>

| | |
|---|---|
| Syntax | `name: <string>` |
| Default | `required` |
| Context | `autoscaling.applications[]` |
| Reload | applies on reload |

Name of the application tier, for logs and status.


<h3 id="autoscaling.cooldown"><code>autoscaling.cooldown</code></h3>

| | |
|---|---|
| Syntax | `cooldown: <seconds>` |
| Default | `30` |
| Context | `autoscaling` |
| Reload | applies on reload |

Minimum time between two scaling actions.


<h3 id="autoscaling.inflight_per_loop"><code>autoscaling.inflight_per_loop</code></h3>

| | |
|---|---|
| Syntax | `inflight_per_loop: <integer>` |
| Default | `256` |
| Context | `autoscaling` |
| Reload | applies on reload |

Requests in flight per event loop that count as fully loaded.


<h3 id="autoscaling.lag_saturated"><code>autoscaling.lag_saturated</code></h3>

| | |
|---|---|
| Syntax | `lag_saturated: <milliseconds>` |
| Default | `5` |
| Context | `autoscaling` |
| Reload | applies on reload |

Loop lag that counts as fully saturated.


<h3 id="autoscaling.mode"><code>autoscaling.mode</code></h3>

| | |
|---|---|
| Syntax | `mode: off \| observe \| web-tier` |
| Default | `off` |
| Context | `autoscaling` |
| Reload | applies on reload |

`off`: never scale; `observe`: classify and log only; `web-tier`: add and remove instances when the web tier is saturated or idle.


<h3 id="autoscaling.p99_target_ms"><code>autoscaling.p99_target_ms</code></h3>

| | |
|---|---|
| Syntax | `p99_target_ms: <integer>` |
| Default | `none` |
| Context | `autoscaling` |
| Reload | applies on reload |

p99 latency (ms) that counts as fully loaded; absent: latency does not raise the pressure.


<h3 id="autoscaling.scale_in_below"><code>autoscaling.scale_in_below</code></h3>

| | |
|---|---|
| Syntax | `scale_in_below: <number>` |
| Default | `0.3` |
| Context | `autoscaling` |
| Reload | applies on reload |

PressureScore below which the pool counts as idle.


<h3 id="autoscaling.scale_in_window"><code>autoscaling.scale_in_window</code></h3>

| | |
|---|---|
| Syntax | `scale_in_window: <seconds>` |
| Default | `60` |
| Context | `autoscaling` |
| Reload | applies on reload |

How long the pressure must stay below `scale_in_below` before an instance is removed.


<h3 id="autoscaling.scale_out_above"><code>autoscaling.scale_out_above</code></h3>

| | |
|---|---|
| Syntax | `scale_out_above: <number>` |
| Default | `0.75` |
| Context | `autoscaling` |
| Reload | applies on reload |

PressureScore above which the web tier is saturated (ADR-0034).


<h3 id="autoscaling.scale_out_window"><code>autoscaling.scale_out_window</code></h3>

| | |
|---|---|
| Syntax | `scale_out_window: <seconds>` |
| Default | `4` |
| Context | `autoscaling` |
| Reload | applies on reload |

How long the pressure must stay above `scale_out_above` before an instance is added.


<h3 id="controller"><code>controller</code></h3>

| | |
|---|---|
| Syntax | `controller: {...}` |
| Default | `required` |
| Context | `controller.yaml` |
| Reload | applies on reload |

Where the controller keeps its state, its control socket, the scalwsd binary and the configuration it runs.


<h3 id="controller.config"><code>controller.config</code></h3>

| | |
|---|---|
| Syntax | `config: <string>` |
| Default | `required` |
| Context | `controller` |
| Reload | applies on reload |

Source of new configuration generations.


<h3 id="controller.listen"><code>controller.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: inherited \| reuseport` |
| Default | `inherited` |
| Context | `controller` |
| Reload | applies on reload |

How instances share the listeners (ADR-0033): `inherited` (default), the controller opens them and hands every instance the same sockets (one accept queue: balanced, nothing to migrate on scale-in); `reuseport`: each instance binds its own SO_REUSEPORT socket (needs net.ipv4.tcp_migrate_req=1 for scale-in).


<h3 id="controller.socket"><code>controller.socket</code></h3>

| | |
|---|---|
| Syntax | `socket: <string>` |
| Default | `required` |
| Context | `controller` |
| Reload | applies on reload |

Local control API (created 0600).


<h3 id="controller.state_dir"><code>controller.state_dir</code></h3>

| | |
|---|---|
| Syntax | `state_dir: <string>` |
| Default | `required` |
| Context | `controller` |
| Reload | applies on reload |

Generations and instance records (created 0700).


<h3 id="controller.webd_binary"><code>controller.webd_binary</code></h3>

| | |
|---|---|
| Syntax | `webd_binary: <string>` |
| Default | `required` |
| Context | `controller` |
| Reload | applies on reload |

The scalwsd binary the controller starts as instances.


<h3 id="instances"><code>instances</code></h3>

| | |
|---|---|
| Syntax | `instances: {...}` |
| Default | `required` |
| Context | `controller.yaml` |
| Reload | applies on reload |

How many scalwsd instances run, on which CPUs, and how they start, drain and restart.


<h3 id="instances.allow_drain_without_migration"><code>instances.allow_drain_without_migration</code></h3>

| | |
|---|---|
| Syntax | `allow_drain_without_migration: true \| false` |
| Default | `false` |
| Context | `instances` |
| Reload | applies on reload |

Allow scale-in without `net.ipv4.tcp_migrate_req=1` (queued connections of a leaving instance are then reset). Default false.


<h3 id="instances.cpus"><code>instances.cpus</code></h3>

| | |
|---|---|
| Syntax | `cpus: <string>` |
| Default | `required` |
| Context | `instances` |
| Reload | applies on reload |

CPUs instances may use, e.g. `"0-5"` or `"0,2,4"`.


<h3 id="instances.cpus_per_instance"><code>instances.cpus_per_instance</code></h3>

| | |
|---|---|
| Syntax | `cpus_per_instance: <integer>` |
| Default | `required` |
| Context | `instances` |
| Reload | applies on reload |

CPUs each instance is pinned to (one event loop each).


<h3 id="instances.drain_timeout"><code>instances.drain_timeout</code></h3>

| | |
|---|---|
| Syntax | `drain_timeout: <seconds>` |
| Default | `30` |
| Context | `instances` |
| Reload | applies on reload |

Time a leaving instance gets to finish its connections.


<h3 id="instances.kill_grace"><code>instances.kill_grace</code></h3>

| | |
|---|---|
| Syntax | `kill_grace: <seconds>` |
| Default | `5` |
| Context | `instances` |
| Reload | applies on reload |

Time after the drain timeout before a leaving instance is killed.


<h3 id="instances.max"><code>instances.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `instances` |
| Reload | applies on reload |

Instances started at most.


<h3 id="instances.max_restarts"><code>instances.max_restarts</code></h3>

| | |
|---|---|
| Syntax | `max_restarts: <integer>` |
| Default | `5` |
| Context | `instances` |
| Reload | applies on reload |

Crashes within `restart_window` after which an instance is not restarted again.


<h3 id="instances.metrics_base_port"><code>instances.metrics_base_port</code></h3>

| | |
|---|---|
| Syntax | `metrics_base_port: <integer>` |
| Default | `9910` |
| Context | `instances` |
| Reload | applies on reload |

Metrics/readiness port of instance i: `metrics_base_port + i` on 127.0.0.1.


<h3 id="instances.min"><code>instances.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `instances` |
| Reload | applies on reload |

Instances kept running at least.


<h3 id="instances.min_free_ram_mib"><code>instances.min_free_ram_mib</code></h3>

| | |
|---|---|
| Syntax | `min_free_ram_mib: <integer>` |
| Default | `512` |
| Context | `instances` |
| Reload | applies on reload |

Free host memory (MiB) required before a new instance starts.


<h3 id="instances.restart_window"><code>instances.restart_window</code></h3>

| | |
|---|---|
| Syntax | `restart_window: <seconds>` |
| Default | `300` |
| Context | `instances` |
| Reload | applies on reload |

Window in which crashes are counted for `max_restarts`.


<h3 id="instances.roll_on_upgrade"><code>instances.roll_on_upgrade</code></h3>

| | |
|---|---|
| Syntax | `roll_on_upgrade: true \| false` |
| Default | `true` |
| Context | `instances` |
| Reload | applies on reload |

Roll instances onto a replaced scalwsd binary when the controller starts (a package upgrade): a copy of the current generation, without reading `config`. Default true; false only logs which instances run the old binary.


<h3 id="instances.start_timeout"><code>instances.start_timeout</code></h3>

| | |
|---|---|
| Syntax | `start_timeout: <seconds>` |
| Default | `20` |
| Context | `instances` |
| Reload | applies on reload |

Time a new instance gets to become ready; it is stopped otherwise.
