Connection Health Monitoring
py-libp2p ships an opt-in connection health monitor as a Python-local QoS layer. It is disabled by default and does not change wire-protocol behavior for peers that do not enable it.
See also:
Connection Health Monitoring Examples — runnable examples and CLI
libp2p.network.health package — module API reference
examples.health_monitoring package — example package automodule
Overview
When enabled via ConnectionConfig.enable_health_monitoring, the swarm runs
ConnectionHealthMonitor, which:
Probes each connection periodically using
/ipfs/ping/1.0.0(notPingService.ping(peer_id), which selects the best connection per peer).Maintains per-connection metrics and a composite
health_score(0.0–1.0).Replaces persistently unhealthy connections using dial-first semantics (a replacement must succeed before the old connection is dropped).
Skips auto-replacement for ConnMgr Protect peers (
tag_store).Integrates with load-balancing strategies
health_basedandlatency_basedfor outbound stream selection.
Relationship to other py-libp2p features
ConnMgr (watermarks, trim, Protect/tags): health replace respects Protect; trimming is unchanged.
Load balancing (
ConnectionConfig.load_balancing_strategy):best,round_robin,least_loaded,health_based,latency_based.Peerstore: optional RTT recording into LatencyEWMA after successful pings.
When to enable
Enable health monitoring when you:
Run multiple connections per peer and want health-aware routing.
Need visibility into connection quality (latency, success rate, scores).
Want automatic dial-first replacement of degraded paths.
Leave it disabled (default) for minimal overhead or when you manage connectivity entirely at the application layer.
Configuration reference
All fields live on libp2p.network.config.ConnectionConfig.
Core toggle
enable_health_monitoring(bool, defaultFalse)Master switch for the monitor service and health data structures.
Timing
health_initial_delay(float, default60.0seconds)Delay before the first monitoring cycle (avoids startup noise).
health_warmup_window(float, default5.0seconds)Skip checks on very new connections.
health_check_interval(float, default60.0seconds)Period between full connection scan cycles.
ping_timeout(float, default5.0seconds)Overall timeout for a single connection ping probe.
Thresholds and replacement
min_health_threshold(float, default0.3)Score below which a connection counts as unhealthy.
min_connections_per_peer(int, default1)Minimum connections to keep; replace is blocked unless critically unhealthy.
max_ping_latency(float, default1000.0ms)Maximum acceptable ping latency before marking unhealthy.
min_ping_success_rate(float, default0.7)Minimum ping success rate before marking unhealthy.
max_failed_streams(int, default5)Failed stream count threshold.
unhealthy_grace_period(int, default3)Consecutive unhealthy evaluations before replace.
critical_health_threshold(float, default0.1)Allows replace even at
min_connections_per_peerwhen score is critical.
Scoring weights
latency_weight(float, default0.4)Weight for latency in
health_score.success_rate_weight(float, default0.4)Weight for ping success rate.
stability_weight(float, default0.2)Weight for connection stability.
Probe behavior (issue #1453)
skip_ping_when_streams_open(bool, defaultFalse)When
True, skip probes on busy connections (legacy behavior). Default probes even when application streams are open.record_ping_latency_in_peerstore(bool, defaultTrue)Record successful ping RTT into peerstore LatencyEWMA (seconds).
abort_connection_on_ping_failure(bool, defaultFalse)When
True, close the probed connection immediately after a failed ping via the connection’s normal Swarm teardown (SwarmConn.close/remove_conn, including notifees and rcmgr). Replacement rules still apply on later ticks; Protect applies to replace, not to this local abort.
Host and Swarm API
All methods are available on IHost (delegates to swarm when monitoring is
enabled).
get_connection_health(peer_id) -> dictPer-peer summary: connection count, average score/latency/success rate, per-connection details via
connectionslist.get_network_health_summary() -> dictGlobal summary:
total_peers,total_connections,average_peer_health,peers_with_issues,peer_details.export_health_metrics(format="json"|"prometheus") -> strJSON export mirrors
get_network_health_summary()structure. Prometheus export exposes gauges such aslibp2p_peers_total,libp2p_connections_total,libp2p_average_peer_health,libp2p_peers_with_issues.get_health_monitor_status() -> dict(async)Service status:
enabled,monitoring_task_started,check_interval_seconds, connection/peer counts.
Operator guide
Enable on a host
from libp2p import new_host
from libp2p.network.config import ConnectionConfig
config = ConnectionConfig(
enable_health_monitoring=True,
health_check_interval=30.0,
load_balancing_strategy="health_based",
)
host = new_host(connection_config=config)
When auto-replace runs vs is skipped
Replace runs when thresholds fail for unhealthy_grace_period consecutive
checks and:
The connection has no open streams (active traffic blocks replace).
The peer is not ConnMgr-protected.
Dial-first replacement succeeds.
Either above
min_connections_per_peerafter removal, or critically unhealthy.
Live demo and GUI
Console script (after install):
health-monitoring-demo --peers 10 --scenario all
Module invocation:
python -m examples.health_monitoring.live_demo --peers 10 --scenario healthy,protect
python -m examples.health_monitoring.live_demo --gui tui
python -m examples.health_monitoring.live_demo --gui web --gui-port 8765
--gui tui opens a terminal table; --gui web serves HTML plus
/api/summary (JSON) and /api/metrics?format=prometheus.
Config-only walkthrough (no connections):
python examples/health_monitoring/basic_example.py
Reading health summaries
summary = host.get_network_health_summary()
peer = host.get_connection_health(some_peer_id)
print(host.export_health_metrics("json"))
Protect a peer from auto-replace (ConnMgr API / tag_store.Protect) before
expecting replace to skip that peer.