# Limitations of iroh: 8 Critical Constraints for Production Deployments

> Explore the critical limitations of iroh for production deployments. Understand QUIC UDP requirements, NAT traversal dependencies, experimental APIs, and essential configurations for rate limiting and storage.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: deep-dive
- Published: 2026-06-21

---

**Iroh requires QUIC/UDP support, depends on relay infrastructure for NAT traversal failures, and ships with experimental APIs behind feature flags, requiring explicit configuration for rate-limiting, persistent storage, and cross-platform compatibility.**

Iroh is a modern Rust networking library developed by n0-computer that enables direct peer-to-peer connections using public keys with automatic hole-punching. While the library automates path selection and fallback mechanisms, understanding the limitations of iroh is essential before deploying it in bandwidth-intensive or restricted network environments.

## Network Protocol Constraints

### QUIC and UDP Dependency

The core networking layer relies exclusively on QUIC via the `noq` crate, which provides authentication, multiplexing, and low-latency communication. However, this design choice means iroh cannot operate in environments that block UDP traffic or use outdated kernel UDP stacks. All hole-punching and relay logic assumes QUIC over UDP is available end-to-end.

### Best-Effort NAT Traversal

Iroh attempts automatic hole-punching to establish direct paths, but success is not guaranteed. When both peers reside behind symmetric NATs or corporate firewalls that block UDP entirely, the library cannot establish a direct connection. In these scenarios, iroh falls back to relay servers, increasing latency and dependence on external infrastructure.

## Infrastructure Dependencies

### Relay Server Requirements

The library requires reachable relay servers for fallback connections when direct paths fail. While n0-computer operates public relays, the ecosystem is still growing, and production deployments may need to run private relays. Deploying `iroh-relay` components adds operational complexity and infrastructure costs.

### Optional Rate Limiting

As noted in the changelog entry **"Rate limiting in router" (#3951)**, iroh provides router-level rate-limiting primitives, but these are disabled by default. Large-scale deployments must explicitly enable and tune rate limiting to protect relay infrastructure from abuse:

```rust
// Example: Enabling rate limiting in router configuration
let router = Router::builder()
    .node(&node)
    .accept(iroh::Protocol::RATE_LIMITED, handler)
    .spawn()
    .await?;

```

## API Stability and Platform Support

### Experimental and Feature-Gated APIs

Many advanced capabilities, including custom transports and address filtering hooks, reside behind `unstable-*` feature flags. These APIs may introduce breaking changes without deprecation cycles, as documented in the changelog under entries like **"Configurable path selection"**. Production code should avoid unstable features unless you can maintain version pins.

### Platform-Specific Limitations

The `iroh-dns-server` component depends on `rustls` with ACME support, which may fail to compile on platforms lacking modern TLS libraries. Additionally, Android support requires specific configuration steps documented in the changelog entry **"Document how to use iroh on Android" (#4183)**:

```toml

# Cargo.toml - Android-specific configuration may require:

[target.'cfg(android)'.dependencies]
rustls = { version = "0.21", features = ["ring"] }

```

## Architectural Limitations

### No Built-In Persistent Storage

The core `iroh` crate provides only the networking layer. Applications requiring data persistence or pub-sub messaging must integrate additional workspace crates like `iroh-blobs` for content-addressed storage or `iroh-gossip` for message propagation:

```rust
// Protocol composition required for persistence
use iroh_blobs::protocol::BlobsProtocol;

let blobs = BlobsProtocol::new(store);
let router = Router::builder()
    .node(&node)
    .accept(BlobsProtocol::ALPN, blobs)
    .spawn()
    .await?;

```

### Throughput and Performance Ceilings

While optimized for low latency, iroh's maximum throughput is constrained by QUIC's congestion control algorithms and underlying OS UDP buffer limits. Multi-gigabit bulk transfers require explicit OS tuning, such as increasing socket buffer sizes beyond default limits.

## Summary

- **Protocol Lock-In**: Requires QUIC/UDP support via the `noq` crate; incompatible with TCP-only networks.
- **NAT Traversal Uncertainty**: Symmetric NATs and UDP-blocking firewalls force relay fallback, increasing latency.
- **Operational Overhead**: Rate limiting (#3951) and private relays require manual configuration.
- **API Instability**: Features behind `unstable-*` flags change without warning.
- **Platform Constraints**: `iroh-dns-server` and Android (#4183) need specific dependency management.
- **Storage Gaps**: Core library lacks persistence; requires `iroh-blobs` or custom protocols.
- **Bandwidth Limits**: QUIC congestion control and UDP buffers cap raw throughput.

## Frequently Asked Questions

### Can iroh work over TCP only?

No. Iroh requires UDP support because the underlying `noq` crate implements QUIC, which mandates UDP for transport. Networks blocking UDP or using outdated kernel stacks cannot run iroh directly.

### Does iroh guarantee direct peer-to-peer connections?

No. NAT traversal is best-effort. When both peers use symmetric NATs or restrictive firewalls, iroh falls back to relay servers, establishing an indirect connection rather than a direct path.

### How do I enable persistent storage in iroh?

You must compose the core networking crate with additional protocols. Import `iroh-blobs` for content-addressed storage or `iroh-gossip` for messaging, then mount them on the router using the appropriate Application-Layer Protocol Negotiation (ALPN) identifiers.

### Is iroh suitable for high-throughput file transfers?

Iroh prioritizes low latency over raw throughput. While capable of file transfers, multi-gigabit speeds require tuning OS UDP buffer sizes and may encounter ceilings imposed by QUIC's congestion control.