Portunus
Features

Multi-target Failover

Up to 8 priority-ordered targets per rule with passive health detection and optional active probes.

Available since v0.7.0. Extends Rule.targets[] from a single target to an ordered list of up to 8.

How it works

  • Lower priority number = higher preference. The client always attempts the highest-preference healthy target first, then walks the remaining targets in priority order on failure.
  • Passive failure detection: 3 consecutive connect failures within 30 s flips a target to Failed; 2 consecutive successes flip it back.
  • Active probes (optional, per rule): set health_check_interval_secs (range 1..=3600) to drive periodic TCP-connect probes from the client.
  • All-failed fallback: when every target is Failed, the client still attempts the highest-priority target rather than giving up.
  • All health state is client-side and ephemeral — it does not survive a client restart.

Push a multi-target rule

# Repeat --target; lower priority wins
portunus-server push-rule edge-01 8443 \
  --target primary.example.com:443@1 \
  --target backup.example.com:443@2 \
  --target standby.example.com:443@3

# Or pass a JSON literal
portunus-server push-rule edge-01 8443 --targets-json '[
  {"host":"primary.example.com","port":443,"priority":1},
  {"host":"backup.example.com","port":443,"priority":2}
]'

The HTTP API accepts a targets[] array on POST /v1/rules. The Web UI exposes an "Add another target" button on the rule push form.

Single-target rules are unchanged

Single-target rules stay byte-identical to v0.6.0 — multi-target lives in a separate code path entered via match targets.len() at rule activation, so existing throughput is unaffected.

Per-target stats

Per-target byte counters surface only on demand to keep the Prometheus cardinality bounded:

# CLI (single-target rules print a no-op note and exit 0)
portunus-server rule-stats <id> --per-target

# HTTP
curl -H "Authorization: Bearer $PORTUNUS_OPERATOR_TOKEN" \
     'http://127.0.0.1:7080/v1/rules/<id>/stats?per_target=true'

# SSE (live stream)
curl -N -H "Authorization: Bearer $PORTUNUS_OPERATOR_TOKEN" \
     'http://127.0.0.1:7080/v1/rules/<id>/stats/stream?per_target=true'

The Web UI rule detail page shows health badges (Healthy / Failed), last-failure / last-success timestamps, and per-target byte counters that update on the existing 5-second SSE cadence.

Default /metrics

One always-on counter: portunus_rule_target_failovers_total{client,rule,owner} captures Healthy↔Failed transitions per rule. Per-target byte counters are never in the default /metrics series.

Capability gate

Multi-target push to a v0.6.0-or-earlier client is rejected at the HTTP layer with 422 multi_target_unsupported_by_client.

Performance

Since v1.7.0 the live byte counters and the Linux splice(2) fast path also apply to the multi-target failover path; per-target accounting is reconciled centrally and closed correctly on error.

On this page