# How to Configure QUIC Transport Settings in Iroh: A Complete Guide

> Learn to configure QUIC transport settings in Iroh using QuicTransportConfig::builder(). Customize defaults and apply them to your Endpoint for enhanced performance.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Use `QuicTransportConfig::builder()` to create a custom transport configuration, then apply it to an `Endpoint` via `Endpoint::builder().transport_config(cfg).build()` to override iroh’s default QUIC parameters.**

Iroh is a next-generation distributed networking toolkit that uses QUIC as its primary transport protocol. Configuring QUIC transport settings in iroh allows you to fine-tune connection lifecycles, multipath behavior, and NAT traversal parameters through the `QuicTransportConfig` builder pattern defined in the `n0-computer/iroh` repository. The default values are specifically optimized for hole-punching and residential NAT traversal, but applications with specific latency, bandwidth, or mobility requirements can adjust these parameters using the builder API.

## Understanding QuicTransportConfig

The `QuicTransportConfig` struct located in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 90-106) encapsulates all transport-level QUIC tuning options. This type uses a **builder pattern** via `QuicTransportConfigBuilder`, which wraps the underlying `noq::TransportConfig` while providing iroh-specific defaults.

When an **Endpoint** is constructed, it stores the transport configuration in its `transport_config` field ([`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), lines 132-139). The defaults chosen in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 154-162) prioritize hole-punching success over raw throughput, making them suitable for peer-to-peer networking but potentially suboptimal for data-center deployments.

## Key Configuration Parameters

### Multipath and Path Management

Control how iroh utilizes multiple network paths simultaneously:

- **`max_concurrent_multipath_paths()`** – Sets the maximum number of simultaneous paths per connection (default: 13). Defined in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 462-473).
- **`max_remote_nat_traversal_addresses()`** – Limits how many addresses the remote peer can advertise for NAT traversal attempts.
- **`send_observed_address_reports()`** – Enables QUIC address discovery, allowing endpoints to learn their public-facing addresses through relay servers.

### Timing and Keep-Alive

Manage connection lifecycle to prevent NAT mapping timeouts:

- **`max_idle_timeout()`** – Duration of inactivity before closing a connection (default: 30 seconds).
- **`keep_alive_interval()`** – Frequency of keep-alive packets sent to maintain NAT bindings.

### MTU and Packet Sizing

- **`initial_mtu()`** – Starting MTU before path MTU discovery begins.
- **MTU discovery settings** – Controls automatic detection of maximum packet size along the network path.

## Building a Custom QUIC Configuration

### Step 1: Create the Builder

Start with `QuicTransportConfig::builder()` to obtain a builder pre-populated with iroh’s optimized defaults.

### Step 2: Customize Parameters

Chain builder methods to override specific values:

```rust
use iroh::endpoint::QuicTransportConfig;

let quic_cfg = QuicTransportConfig::builder()
    .max_concurrent_multipath_paths(20)
    .max_remote_nat_traversal_addresses(12)
    .max_idle_timeout(Some(
        iroh::endpoint::quic::IdleTimeout::from_millis(15_000).into(),
    ))
    .initial_mtu(1400)
    .keep_alive_interval(std::time::Duration::from_secs(5))
    .build();

```

### Step 3: Apply to Endpoint

Pass the configuration when constructing an `Endpoint` using the `transport_config()` setter defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 658-670):

```rust
use iroh::endpoint::Endpoint;

let endpoint = Endpoint::builder()
    .transport_config(quic_cfg)
    .build()
    .await?;

```

For existing endpoints, use `endpoint.with_transport_config(cfg)` to replace the configuration.

## Integration with Network Reporting

For QUIC address discovery used in net-report probes, integrate the configuration through `Options::quic_config()` as defined in [`iroh/src/net_report/options.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/net_report/options.rs) (lines 15-22):

```rust
use iroh::net_report::Options;

let opts = Options::new(tls_config)
    .quic_config(Some(quic_cfg));

```

This enables the relay client to utilize your custom transport settings when performing address discovery and NAT type detection.

## Complete Working Example

This example demonstrates configuring iroh for high-churn mobile environments with aggressive keep-alives and extended multipath support:

```rust
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Build custom QUIC transport config
    let quic_cfg = iroh::endpoint::QuicTransportConfig::builder()
        .max_concurrent_multipath_paths(30)
        .max_remote_nat_traversal_addresses(16)
        .max_idle_timeout(Some(
            iroh::endpoint::quic::IdleTimeout::from_millis(45_000).into(),
        ))
        .initial_mtu(1400)
        .keep_alive_interval(std::time::Duration::from_secs(5))
        .build();

    // 2. Create endpoint with custom config
    let endpoint = iroh::endpoint::Endpoint::builder()
        .transport_config(quic_cfg)
        .build()
        .await?;

    // 3. Use the endpoint normally
    let conn = endpoint
        .connect("example.iroh.link:443".parse()?, Default::default())
        .await?;
    
    Ok(())
}

```

## Summary

- **`QuicTransportConfig`** in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) is the central configuration type for all QUIC tuning.
- Use the **builder pattern** via `QuicTransportConfig::builder()` to customize multipath limits, idle timeouts, and MTU settings.
- Apply configurations using **`Endpoint::builder().transport_config(cfg)`** as implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 658-670).
- **Default values are optimized for P2P hole-punching**—modifying them without understanding the impact on NAT traversal may degrade connectivity.
- Reference specific implementation details in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 90-106 for the builder, lines 154-162 for defaults, and lines 462-473 for multipath settings).

## Frequently Asked Questions

### How do I increase the number of concurrent paths for multipath QUIC?

Use the `max_concurrent_multipath_paths()` method on the builder to raise the limit above the default of 13. This controls how many simultaneous network paths a single connection can utilize, which is critical for iroh’s multipath performance as implemented in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 462-473). Increasing this value benefits mobile devices switching between Wi-Fi and cellular networks but consumes more system resources per connection.

### Can I modify QUIC settings after creating an Endpoint?

Yes. Use the `with_transport_config()` method defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 658-670) to replace the transport configuration on an existing endpoint. However, note that this change only affects future QUIC connections and streams; existing connections retain the transport parameters active at the time of their creation.

### What is the default idle timeout and how do I change it?

The default idle timeout is 30 seconds, configured to balance NAT mapping retention with timely connection cleanup. To modify it, pass a `VarInt`-compatible duration to `max_idle_timeout()`:

```rust
let timeout = iroh::endpoint::quic::IdleTimeout::from_millis(60_000);
let cfg = QuicTransportConfig::builder()
    .max_idle_timeout(Some(timeout.into()))
    .build();

```

Be cautious when extending this value beyond 60 seconds, as overly long timeouts may exhaust file descriptors and memory in high-churn environments.

### Where are iroh’s default QUIC values defined?

Default values that differ from standard Quinn behavior are explicitly set in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) (lines 154-162). These defaults prioritize hole-punching success and NAT traversal reliability over raw throughput, making them distinct from generic QUIC implementations used in traditional client-server architectures.