IP addresses break, dial keys instead

Modular networking stack for direct connections between devices

spacedrive logo
nous logo
shaga logo
rave logo
delta_chat logo
holochain logo

Fast connections.
Anywhere.
Forever.

Dial any endpoint running anywhere, big or small — cloud servers, tablets, or Raspberry Pis.

The core technology is open source and relays are stateless — host across regions and clouds, or self-host anywhere.

Learn about Relays

Save cloud costs

Direct connections bypass NATs and firewalls. Relays keep you connected when they can't.

Sync anything, anywhere

Files, structured data, video, RPC — or write your own protocol.

E2E Encrypted, Always

Every connection is end-to-end encrypted over QUIC.

Deploy a dedicated relay

Self-host or use our managed infrastructure across multiple regions.

Nous

“Doubling the network speed halves our compute budget. That's the difference between a $1M model and a $500K model.”

Ari Lotter
Principal Engineer at Nous
Read the Case Study

How are people using iroh?

Deploy, Monitor, Fix

All commits to iroh's main branch run through a growing set of simulations & tests.

iroh provides opt-in observability and custom metrics — track connection health and throughput across all your devices and services.

Monitor your App

Modular toolkit

Dozens of open-source, composable protocols built on top of iroh. Mix & match to get the feature set you need.

Start building.

Read the Docs

main.rs

// a program that creates two endpoints & sends a ping between them
use anyhow::Result;
use iroh::{Endpoint, protocol::Router};
use iroh_ping::Ping;

#[tokio::main]
async fn main() -> Result<()> {
    // create the receive side
    let recv_ep = Endpoint::builder().bind().await?;
    let recv_router = Router::builder(recv_ep.clone())
        .accept(iroh_ping::ALPN, Ping::new())
        .spawn();
    recv_ep.online().await;
    let addr = recv_router.endpoint().addr();

    // create a send side & send a ping
    let send_ep = Endpoint::builder().bind().await?;
    let send_pinger = Ping::new();
    let rtt = send_pinger.ping(&send_ep, addr).await?;
    println!("ping took: {rtt:?} to complete");

    Ok(())
}

From the Blog