PHP
Managed PHP-FPM pools over FastCGI, front controller and PATH_INFO, or an external FastCGI endpoint.
1.06× nginx 1.31.6, same PHP-FPM pool. Varies run to run; under investigation.
Linux · Rust · Adaptive Runtime
A Linux web and application server in Rust that adds web-tier capacity only when the web tier is the bottleneck.
nginx 1.31.6 · TLS + HTTP/2 small file
nginx 1.31.6 · response cache hits
nginx 1.31.6 · fixed in-memory response, ScalWS behind
class=WebTierSaturated action=None reason="pressure 0.79; at max_instances 3"
Three instances on three CPUs: 144.5k req/s, p99 10 ms, zero errors. At max_instances the controller logs the reason instead of acting.
Measured: D5 burst, idle to 1024 connections, zero errors. Pressure bars and values inside log lines are illustrative.
1.29× nginx 1.31.6 in the tested TLS + HTTP/2 small-file workload and 1.54× on cache hits. Behind: Small static file 0.98×, 1 MiB static file 0.99×, Fixed response 0.86×, Reverse proxy 0.83×, Node.js 0.98×, Python (uvicorn) 0.97×. Same bare-metal host, same pinned cores for every server. Opt-in own HTTP/1 server and client (http1_server: experimental, upstream_client: experimental): 1.27× on TLS + HTTP/2, 1.70× on cache hits, 0.93× on fixed responses.
Full results and methodology →Kubernetes ingress benchmark →
“Every N requests, start another instance” is wrong whenever the application behind the server is the limit. The ScalWS controller first decides which tier is saturated, and only a saturated web tier may act.
WebTierSaturated
PressureScore above 0.75, driven by CPU together with event-loop lag. No application at its CPU allotment.
ScaleOut within min, max, memory and cooldown limits.
PhpSaturated · NodeSaturated · PythonSaturated
The application uses at least 90 % of its CPU allotment. Even if the web tier is busy too, more instances would not raise throughput.
None, plus a logged recommendation for the operator.
MemoryPressure · ConnectionPressure · InsufficientEvidence
Low free memory, many requests in flight with idle CPUs, or too few samples.
None, with the reason in the log.
Measured in front of PHP-FPM on one CPU: 11.8k, 11.8k and 11.8k req/s with 1, 2 and 3 instances. Efficiency 0.50 and 0.33. ADR-0034
Instances accept from listening sockets the controller opens once and hands them (or from a kernel SO_REUSEPORT group) and terminate TLS themselves. scalws-controller watches their metrics and runs their lifecycle. If it stops, instances keep serving.
Control plane and data plane →control plane
data plane
Bursts from idle to 1024 connections, three in a row, zero errors, autoscaling in web-tier mode with one CPU per instance. Instances are counted at the end of each burst; each instance adds a CPU. With the same CPUs, one larger instance does about as well: 1.00× to 1.05× across web-tier scenarios. Multi-instance buys the ability to add and remove capacity, not more work per CPU.
Scaling data →Spawned with an id, a CPU set and a configuration generation. Bound, not listening.
Configuration prepared, runtimes and caches initialised.
Readiness passed. Still no traffic.
Starts accepting. New connections arrive.
Stops accepting first; the other instances keep the queue. In-flight requests finish.
Drain testing found and fixed four defects that also affected a single instance on every SIGTERM. Lifecycle, generations and recovery →
In the packages and opt-in in the configuration: HTTP/3 (http3: true on a listener). Experimental and opt-in at build time: eBPF accounting. Experimental and opt-in in the configuration: the own HTTP/1 server and upstream client (the default stays hyper). The multi-node control plane is designed (ADR-0021), not built. .htaccess support is a subset, not Apache compatibility.
Managed PHP-FPM pools over FastCGI, front controller and PATH_INFO, or an external FastCGI endpoint.
1.06× nginx 1.31.6, same PHP-FPM pool. Varies run to run; under investigation.
Supervised processes, one socket each, round-robin over ready workers. Or any upstream.
0.98× nginx 1.31.6, application-bound. OpenLiteSpeed is ahead (8.08k against 7.97k req/s).
ASGI and WSGI through uvicorn, hypercorn or gunicorn, with virtualenvs.
0.97× nginx 1.31.6, same uvicorn server, application-bound.
Supervised with readiness, crash backoff, restart-loop detection and graceful drain. Under the Adaptive Runtime controller, application tiers must be external endpoints: managed pools are refused so instances do not each start their own.
Signed apt, dnf, zypper and apk repositories for the RHEL family, Fedora, Debian, Ubuntu, openSUSE, SLES and Alpine (x86_64). scalwsctl check runs the exact prepare path a reload would. Building from source is in the README.
curl -fsSL https://apt.scalws.com/scalws-archive-keyring.gpg \
-o /usr/share/keyrings/scalws-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/scalws-archive-keyring.gpg] https://apt.scalws.com stable main' \
> /etc/apt/sources.list.d/scalws.list
apt update && apt install scalws
scalwsctl check && systemctl enable --now scalws-controller