RelayMode Default vs Disabled vs Custom in iroh: Endpoint Connection Modes Explained

RelayMode::Default uses iroh's built-in production relays for NAT traversal, RelayMode::Disabled (sometimes referred to as "NoRelay") blocks all relay traffic to enforce direct peer-to-peer connections only, and RelayMode::Custom accepts an explicit RelayMap for private relay infrastructure.

The RelayMode enum in the n0-computer/iroh repository controls how an Endpoint discovers and utilizes relay servers during connection establishment. Defined in [iroh/src/endpoint.rs](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), this configuration determines whether your application relies on public relay servers, operates without relay assistance, or connects to specific self-hosted relays.

RelayMode::Default: Production Relay Infrastructure

RelayMode::Default configures the endpoint to use the production relay map embedded in the library. According to the source code at line 1929, this variant invokes crate::defaults::prod::default_relay_map() to retrieve the list of public relays operated by the iroh team.

Use this mode for general internet-facing applications where you require reliable, globally-available relays without manual configuration. When direct hole-punching fails due to restrictive NATs or firewalls, the endpoint automatically falls back to these production relays to maintain connectivity.

RelayMode::Disabled: Direct-Only Communication

RelayMode::Disabled disables all relay functionality entirely. As implemented in the source branch at lines 1929-1930, the endpoint will never attempt to hole-punch or forward traffic through relay servers. All connection attempts must succeed via direct peer-to-peer paths or fail immediately.

Select this mode when operating in trusted, fully reachable networks such as internal LANs or VPNs where you want to eliminate relay traffic entirely. This configuration is also available via the presets module in [iroh/src/endpoint/presets.rs](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/presets.rs) for quick "no relay" endpoint setup.

RelayMode::Custom: Private Relay Deployments

RelayMode::Custom(RelayMap) accepts an explicit relay map containing your own relay URLs. The variant definition at lines 1922-1924 wraps a user-provided RelayMap, and the helper constructor RelayMode::custom() (lines 51-53) simplifies construction from any iterator of URLs.

This mode is essential for private deployments, corporate environments with specific firewall requirements, or edge-located relays. Unlike Default, which pulls from iroh/defaults/prod, Custom uses exactly the relays you specify via the RelayUrl type defined in [iroh-base/src/relay_url.rs](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/relay_url.rs).

Key Differences in Network Behavior

The three modes differ fundamentally in their source of relay URLs and fallback behavior:

  • Source of URLsDefault pulls the built-in production list; Custom uses your provided list; Disabled uses none.
  • Connection Resilience – With Default or Custom, the endpoint can fall back to relays when direct paths fail. With Disabled, connection failures are terminal.
  • Configuration ComplexityDefault requires no additional code; Custom requires building a RelayMap; Disabled is a single variant value.

Configuring Your Endpoint: Code Examples

The following patterns from [iroh/examples/listen.rs](https://github.com/n0-computer/iroh/blob/main/iroh/examples/listen.rs#L31) demonstrate practical usage of each relay mode:

use iroh::{Endpoint, RelayMode};

fn main() -> anyhow::Result<()> {
    // Default: Use production relays shipped with iroh
    let endpoint_default = Endpoint::builder()
        .relay_mode(RelayMode::Default)
        .bind()?;
    
    // Disabled (No Relay): Direct connections only
    let endpoint_disabled = Endpoint::builder()
        .relay_mode(RelayMode::Disabled)
        .bind()?;
    
    // Custom: Specific private relay servers
    let custom_map = iroh::RelayMap::from_iter([
        "https://relay1.example.com/".parse()?,
        "https://relay2.example.com/".parse()?,
    ]);
    let endpoint_custom = Endpoint::builder()
        .relay_mode(RelayMode::Custom(custom_map))
        .bind()?;
    
    Ok(())
}

For convenience, the RelayMode::custom() helper (lowercase) automatically wraps your URLs into a RelayMap, while the RelayMode::Custom variant (uppercase) accepts a pre-constructed map directly.

Summary

  • RelayMode::Default leverages the built-in production relay map (defaults::prod) for automatic NAT traversal without configuration.
  • RelayMode::Disabled eliminates all relay functionality, requiring successful direct peer-to-peer paths or failing the connection.
  • RelayMode::Custom requires a manually constructed RelayMap for complete control over relay server selection in private networks.

Frequently Asked Questions

What is the difference between RelayMode::Disabled and NoRelay?

RelayMode::Disabled is the actual enum variant name in [iroh/src/endpoint.rs](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), while "NoRelay" is the conceptual description used in documentation and the presets module. Both refer to the same behavior: completely disabling relay assistance and forcing direct connections only.

When should I use RelayMode::Custom instead of Default?

Use RelayMode::Custom when operating in restricted network environments, testing self-hosted relay infrastructure, or deploying within corporate networks that block external relay endpoints. RelayMode::Default is preferable for general applications requiring the global availability of iroh's public relay fleet without configuration overhead.

How does RelayMode affect connection establishment?

RelayMode::Disabled attempts only direct connections, failing fast when peers are unreachable. RelayMode::Default and RelayMode::Custom may increase initial connection latency while attempting UDP hole-punching, but ultimately succeed by falling back to relay servers when direct paths fail.

Can I change RelayMode on an existing Endpoint?

No. The RelayMode is fixed during Endpoint construction via the builder pattern and cannot be modified dynamically. To alter relay behavior, you must create a new Endpoint instance with the desired configuration using Endpoint::builder().

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →