Fri, Jan 9, 2026

Network overview - 2026-01-09

Network overview using Xatu sentry node observations on Ethereum mainnet.

Show code
display_sql("xatu_client_connectivity", target_date)
View query
SELECT
    toStartOfInterval(event_date_time, INTERVAL 1 hour) AS hour_bucket,
    remote_peer_id_unique_key AS peer_id,
    remote_protocol AS protocol,
    remote_transport_protocol AS transport_protocol,
    remote_port AS port,
    remote_agent_implementation AS client_name,
    meta_client_name AS local_name,
    remote_geo_country_code AS geo_country_code
FROM libp2p_connected_local
WHERE meta_network_name = 'mainnet'
  AND event_date_time >= '2026-01-09' AND event_date_time < '2026-01-09'::date + INTERVAL 1 DAY
ORDER BY hour_bucket ASC
Show code
df = load_parquet("xatu_client_connectivity", target_date)

Total unique peers

Number of unique peers observed by Xatu sentry nodes throughout the day.

Show code
df_unique = df.groupby("hour_bucket")["peer_id"].nunique().reset_index()
df_unique.columns = ["hour_bucket", "unique_peers"]

fig = px.line(
    df_unique,
    x="hour_bucket",
    y="unique_peers",
)
fig.update_layout(
    xaxis_title=None,
    yaxis_title="Unique peers",
    height=400,
)
fig.show()

Client distribution

Distribution of unique peers by client implementation over time. Each peer is assigned to a single client based on their most recently observed agent string.

Show code
# Filter out empty client names and deduplicate per hour/peer
df_clients = df[df["client_name"].notna() & (df["client_name"] != "")].copy()
df_clients = df_clients.sort_values(["hour_bucket", "peer_id", "client_name"], ascending=[True, True, False])
df_clients = df_clients.drop_duplicates(subset=["hour_bucket", "peer_id"], keep="first")

df_client_counts = df_clients.groupby(["hour_bucket", "client_name"]).size().reset_index(name="peers")

fig = px.area(
    df_client_counts,
    x="hour_bucket",
    y="peers",
    color="client_name",
)
fig.update_layout(
    xaxis_title=None,
    yaxis_title="Peers",
    legend_title="Client",
    height=500,
)
fig.show()

Connections per Xatu node

Number of unique peers connected to each Xatu sentry node over time.

Show code
df_xatu = df.groupby(["hour_bucket", "local_name"])["peer_id"].nunique().reset_index()
df_xatu.columns = ["hour_bucket", "local_name", "peers"]
df_xatu["local_name"] = df_xatu["local_name"].str.replace("ethpandaops/mainnet/", "", regex=False)

fig = px.line(
    df_xatu,
    x="hour_bucket",
    y="peers",
    color="local_name",
)
fig.update_layout(
    xaxis_title=None,
    yaxis_title="Connected peers",
    legend=dict(
        title="Xatu node",
        orientation="h",
        yanchor="top",
        y=-0.2,
        xanchor="center",
        x=0.5,
    ),
    height=500,
)
fig.show()

Transport protocol distribution

Distribution of connections by IP protocol (IPv4/IPv6) and transport protocol (TCP/QUIC) combinations.

Show code
# Group transports per peer/hour/protocol
df_transport = (
    df.groupby(["hour_bucket", "peer_id", "protocol"])["transport_protocol"]
    .apply(lambda x: " & ".join(sorted(x.dropna().unique())))
    .reset_index()
)
df_transport["protocol_combos"] = df_transport["protocol"] + " + (" + df_transport["transport_protocol"] + ")"

df_proto_counts = df_transport.groupby(["hour_bucket", "protocol_combos"]).size().reset_index(name="peers")

fig = px.line(
    df_proto_counts,
    x="hour_bucket",
    y="peers",
    color="protocol_combos",
)
fig.update_layout(
    xaxis_title=None,
    yaxis_title="Connected peers",
    legend_title="Protocol",
    height=500,
)
fig.show()

Port popularity

Most commonly used ports by connected peers. Standard Ethereum P2P port is 30303.

Show code
# Count unique peers per port
df_ports = df.drop_duplicates(subset=["peer_id", "port"]).groupby("port").size().reset_index(name="peers")
df_ports = df_ports.sort_values("peers", ascending=False).head(20)
df_ports["port"] = df_ports["port"].astype(str)

fig = px.bar(
    df_ports,
    x="port",
    y="peers",
)
fig.update_xaxes(type="category")
fig.update_layout(
    xaxis_title="Port",
    yaxis_title="Peers",
    height=400,
)
fig.show()