Nyx by Example

Proxy Health Checks

Periodic TCP probes detect unhealthy upstreams. After N consecutive failures (threshold), the upstream is marked unhealthy and traffic is routed elsewhere. On recovery, it's automatically re-enabled.

Code

// nyx-proxy health checks — TCP probe upstreams periodically
// Health checks nyx-proxy — probe TCP de upstreams

var failures: int = 0
var threshold: int = 3
var healthy: bool = true

// Try to connect to the upstream — returns true if reachable
fn probe_upstream(host: String, port: int) -> bool {
    let fd: int = tcp_connect(host, port)
    if fd < 0 { return false }
    tcp_close(fd)
    return true
}

fn check_loop(host: String, port: int) -> int {
    // A typical health check loop (runs in a separate thread)
    var iterations: int = 0
    while iterations < 3 {
        let ok: bool = probe_upstream(host, port)
        if ok {
            if not healthy {
                print("upstream RECOVERED: " + host + ":" + int_to_string(port))
                healthy = true
            }
            failures = 0
        } else {
            failures = failures + 1
            print("probe failed (" + int_to_string(failures) + "/" + int_to_string(threshold) + ")")
            if failures >= threshold and healthy {
                print("upstream UNHEALTHY: " + host + ":" + int_to_string(port))
                healthy = false
            }
        }
        sleep(1000)
        iterations = iterations + 1
    }
    return 0
}

fn main() -> int {
    // Check a local upstream (likely fails if nothing listening on 3001)
    check_loop("127.0.0.1", 3001)
    print("final state: healthy=" + int_to_string(healthy))
    return 0
}

Output

probe failed (1/3)
probe failed (2/3)
probe failed (3/3)
upstream UNHEALTHY: 127.0.0.1:3001
final state: healthy=0

Explanation

A proxy is only as reliable as the weakest backend it still trusts. Health checks decouple "is this upstream reachable?" from "is a user waiting on it right now?" by probing asynchronously — a dedicated thread opens a TCP connection every N seconds and updates a shared health flag. The threshold (here 3) prevents flapping: a single network glitch shouldn't evict a backend from rotation, but three in a row probably means something's really wrong. Recovery is symmetric — one successful probe flips healthy back to true — so restarts heal themselves without operator action. In production, nyx-proxy runs one of these loops per upstream and the forwarder consults the health map on every request.

← Previous Next →

Source: examples/by-example/87-proxy-health.nx