# Health checks and process supervision on Windows

> Design liveness vs readiness endpoints, supervise Node/Python/Go services, and tune IIS app-pool ping/rapid-fail without crash loops.

**Tested on**

- Build: 26100.33650
- Edition: Standard / Datacenter
- Architecture: x64
- Evidence: E1
- Verified: 2026-10-29

## The short answer

Two different checks:

- **Liveness** — is the process alive? Restart if not.
- **Readiness** — can it serve? Remove from the proxy if not.

Do not use one endpoint for both. A readiness check that hits the database will fail during a DB outage and cause a restart loop that makes it worse.

## Endpoints

- `/healthz` — process alive, no dependencies; cheap.
- `/readyz` — can serve: DB/cache/storage with short timeouts; returns 503 when not ready.
- Never expose internal details (versions, connection strings) publicly; restrict to localhost/proxy.

## IIS app pool

- **Ping**: `PingEnabled`, `PingInterval` (default 30s), `PingResponseTime`.
- **Rapid-fail protection**: `RapidFailProtection`, `RapidFailProtectionMaxCrashes` (default 5 in 5 min). When tripped, the pool stops — a good safety valve, but it means “down until fixed”.
- **Start mode**: `OnDemand` vs `AlwaysRunning`; `AlwaysRunning` + preload for latency-sensitive sites.
- **Idle timeout**: disabling keeps the app warm but hides leaks; monitor.

```powershell
Get-ItemProperty IIS:\AppPools\apppool | Select-Object name,startMode,processModel
```

## Windows services

- NSSM/WinSW `onfailure restart` with a delay (10s+), not an instant loop.
- Set a restart throttle/limit so a permanently broken app does not spin forever.
- Log the exit code; restart without a reason is not a fix.

## Proxy health

- Nginx OSS: passive checks (`max_fails`, `fail_timeout`); active checks are in NGINX Plus.
- ARR farm: health test path + interval.
- Remove a failing node from rotation; alert on repeated failures.

> **Caution: Restart loops hide root cause**
>
> A service that restarts every 10s looks “supervised” but never serves. Alert on restart count, and fix the crash (config, port, DB, permissions).

## Verify

```powershell
curl.exe -I http://127.0.0.1:3000/healthz
curl.exe -I http://127.0.0.1:3000/readyz
Get-IISAppPool apppool | Select-Object Name,State
Get-WinEvent -LogName Application -MaxEvents 20 | Where-Object ProviderName -match 'Application Error'
```

## Lab boundary

E1. The lab did not configure app-pool ping/rapid-fail or a watchdog; the settings are the production design for Server 2025.

## Sources

- [Microsoft Learn — Application pool settings](https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/)
- [Microsoft Learn — Health monitoring](https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/processmodel/)
- [nginx — upstream health checks](https://nginx.org/en/docs/http/ngx_http_upstream_hc_module.html)

---

Source: https://windows.homes/en/server/ops/health/
