# Iroh Node Performance Benchmarks: Complete Guide to QUIC Throughput and Latency Testing

> Discover iroh node performance benchmarks with its dedicated iroh-bench crate. Test QUIC latency, throughput, and relay performance using configurable command-line benchmarks.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: performance
- Published: 2026-07-04

---

**Iroh provides a dedicated `iroh-bench` crate that measures QUIC connection latency, bidirectional throughput, stream multiplexing efficiency, and relay performance through configurable command-line benchmarks.**

The `n0-computer/iroh` repository ships with a comprehensive benchmarking suite designed to exercise core networking libraries including the **noq** QUIC implementation, relay client, and transport layers. These benchmarks allow developers to quantify node performance across real-world network conditions, from direct peer-to-peer connections to relay-mediated scenarios. The suite integrates directly into CI pipelines to catch performance regressions before they reach production.

## Benchmark Architecture and Core Metrics

The benchmarking framework resides in the `iroh/bench` crate and implements six primary performance dimensions. Each metric maps to specific source files and measurement strategies within the codebase.

### Connection Latency Measurement

Connection latency tracks the time required to establish a QUIC handshake, including 0-RTT scenarios when available. In [`iroh/bench/src/iroh.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/iroh.rs), the `run_client` function instantiates an endpoint and records the duration of `endpoint.connect` calls. The benchmark captures the full handshake duration from `Endpoint::bind()` through successful connection establishment, providing millisecond-precision timing data for connection-oriented performance analysis.

### Throughput and Transfer Statistics

Throughput benchmarks measure bytes-per-second performance on bidirectional streams. The `TransferResult` struct in [`iroh/bench/src/stats.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/stats.rs) aggregates `bytes_sent` and `elapsed` duration to compute megabits-per-second (Mbps) metrics. During execution, the benchmark opens bidirectional streams via `conn.open_bi().await` and repeatedly writes known-size payloads while the stats module collects timing data. This approach yields accurate bandwidth measurements that account for both transmission overhead and application-layer processing.

### Stream Multiplexing Efficiency

To evaluate concurrent stream handling, the benchmark spawns multiple simultaneous streams within a single connection. The bulk benchmark implementation in [`iroh/bench/src/iroh.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/iroh.rs) uses `client_benchmark` to generate concurrent load, measuring how many streams the endpoint can sustain without contention. This metric directly impacts real-world applications that need to transfer multiple data chunks simultaneously over a single QUIC connection.

### Relay Performance Testing

When the `--with-relay` flag is enabled, the benchmark suite spins up a local `iroh-relay` instance and routes connections through it. As implemented in [`iroh/bench/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/lib.rs), this mode measures round-trip latency and bandwidth degradation introduced by relay indirection. The same statistical gathering applies, allowing direct comparison between direct peer connections and relay-mediated pathways.

## Running the Benchmark Suite

The `iroh-bench` crate provides multiple execution modes through cargo commands, ranging from simple latency tests to high-concurrency stress scenarios.

### Basic Client-Server Benchmarks

Run a standard performance test against a local endpoint with library metrics enabled:

```bash
cargo run -p iroh-bench -- \
    --addr 127.0.0.1:4433 \
    --duration 30s \
    --metrics

```

This command executes the default benchmark defined in [`iroh/bench/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/lib.rs), parsing CLI arguments and orchestrating the client-server interaction. The `--metrics` flag exposes internal `iroh-net` counters including packets sent, packets received, and retransmission counts.

### Stress Testing with Bulk Operations

For high-load scenarios, use the `bulk` binary located at [`iroh/bench/src/bin/bulk.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/bin/bulk.rs) to spawn multiple concurrent clients:

```bash
cargo run -p iroh-bench --bin bulk -- \
    --clients 8 \
    --payload-size 4MiB \
    --duration 60s

```

The bulk benchmark stress-tests node capacity by running multiple simultaneous connections, each opening bidirectional streams and transferring large payloads. This reveals performance characteristics under contention that single-connection tests might mask.

## Configuration Options and Worker Scaling

The benchmark suite supports granular runtime configuration through command-line flags defined in [`iroh/bench/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/lib.rs):

- **`--workers-per-endpoint`**: Controls Tokio runtime worker thread allocation per endpoint, enabling scalability testing across different CPU core configurations
- **`--with-relay`**: Enables relay-mediated connectivity testing
- **`--metrics`**: Prints internal library counters via `IrohNet::counters()`

Test relay performance with increased worker threads:

```bash
cargo run -p iroh-bench -- \
    --addr 127.0.0.1:4433 \
    --with-relay \
    --metrics \
    --workers-per-endpoint 4

```

The CLI parses `workers_per_endpoint` and creates the specified number of Tokio runtime workers for each endpoint, allowing assessment of how thread pool sizing affects throughput and latency. This configuration mirrors production deployment scenarios where runtime resource allocation directly impacts node performance.

## Summary

- The `iroh-bench` crate provides comprehensive performance testing for QUIC connections, throughput, and relay scenarios
- Core measurement logic resides in [`iroh/bench/src/iroh.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/iroh.rs) for connection handling and [`iroh/bench/src/stats.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/stats.rs) for metric computation
- Use `--with-relay` to quantify relay-induced latency versus direct connections
- The `--workers-per-endpoint` flag enables thread-scaling analysis for production capacity planning
- CI integration in [`.github/workflows/tests.yaml`](https://github.com/n0-computer/iroh/blob/main/.github/workflows/tests.yaml) ensures performance regressions are caught automatically

## Frequently Asked Questions

### How does iroh measure connection latency in benchmarks?

The benchmark records the duration of `endpoint.connect(addr, ALPN).await` calls in [`iroh/bench/src/iroh.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/iroh.rs) within the `run_client` function. This captures the full QUIC handshake time including TLS negotiation and 0-RTT resumption when applicable.

### What throughput metrics does iroh-bench report?

The suite calculates megabits-per-second (Mbps) through the `TransferResult` struct in [`iroh/bench/src/stats.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/stats.rs), which tracks `bytes_sent` and `elapsed` time during bidirectional stream operations. The metric accounts for payload transmission plus protocol overhead.

### Can I benchmark iroh node performance with a relay server?

Yes. Pass the `--with-relay` flag to spin up a local relay instance and route traffic through it. This measures round-trip latency and bandwidth when direct peer-to-peer connectivity is unavailable, as implemented in the CLI parsing logic of [`iroh/bench/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/lib.rs).

### How do I test concurrent stream performance?

Use the `bulk` binary ([`iroh/bench/src/bin/bulk.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/bench/src/bin/bulk.rs)) with the `--clients` flag to spawn multiple simultaneous connections. Each client opens bidirectional streams via `conn.open_bi()`, allowing you to measure how the endpoint handles concurrent load and identify multiplexing bottlenecks.