Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Fallback image description

JetStream

crates.io docs.rs Build Status Release Please🙏! benchmark pull requests crates.io downloads

JetStream is an RPC framework built on top of s2n-quic, iroh, and p9. It’s designed to be a high performance, low latency, secure, and reliable RPC framework.

Features:

For detailed API documentation, see the rustdoc documentation.

Examples

JetStream Cloudflare

Let’s say you’ve defined a service like so

use jetstream::prelude::*;

#[cfg(feature = "server")]
mod server;

#[service]
pub trait Radar {
    async fn ping(&mut self) -> Result<()>;
}

The glue code for running it on Cloudflare Workers is

use jetstream::cloudflare::DefaultHtmlFallback;
use worker::{event, *};

use crate::{radar_protocol, Radar};
struct RadarWorker;

impl Radar for RadarWorker {
    async fn ping(&mut self) -> jetstream::prelude::Result<()> {
        Ok(())
    }
}

#[event(fetch)]
async fn fetch(
    req: Request,
    env: Env,
    ctx: worker::Context,
) -> worker::Result<Response> {
    let handler = radar_protocol::RadarService { inner: RadarWorker };
    let mut router =
        jetstream::cloudflare::Router::<DefaultHtmlFallback>::new([handler]);
    router.fetch(req, env, ctx).await
}

The code for connecting to it is as follows:

#![cfg(feature = "client")]
use std::time::Instant;

use argh::FromArgs;
use jetstream::{
    prelude::{jetstream_rpc::HEADER_KEY_JETSTREAM_PROTO, tracing},
    websocket::tokio_tungstenite::{
        connect_async, tungstenite::client::IntoClientRequest,
    },
};
use jetstream_radar::{
    radar_protocol::{self, RadarChannel},
    Radar,
};
use reqwest::header::HeaderValue;
use url::Url;

#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct Client {
    #[argh(subcommand)]
    nested: Nested,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum Nested {
    Ping(Ping),
}

#[derive(FromArgs, PartialEq, Debug)]
/// First subcommand.
#[argh(subcommand, name = "ping")]
struct Ping {
    #[argh(
        option,
        default = "Url::parse(\"wss://radar.jetstream.rs\").unwrap()"
    )]
    /// url to call
    url: Url,
}

#[tokio::main]
async fn main() {
    rustls::crypto::ring::default_provider()
        .install_default()
        .expect("Failed to install rustls crypto provider");

    let args: Client = argh::from_env();
    match args.nested {
        Nested::Ping(web_socket) => {
            tracing::info!("Connecting to {}", web_socket.url);
            let mut req = web_socket.url.clone().into_client_request().unwrap();
            // this is a custom header, doesn't have anything to do with websocket handshake
            req.headers_mut().insert(
                HEADER_KEY_JETSTREAM_PROTO,
                HeaderValue::from_static(radar_protocol::PROTOCOL_VERSION),
            );

            tracing::info!("Attempting websocket connection...");
            let (ws_stream, response) = connect_async(req).await.unwrap();
            tracing::info!(
                "Connected! Response status: {:?}",
                response.status()
            );

            let ws_transport = jetstream::websocket::WebSocketTransport::<
                RadarChannel,
            >::from(ws_stream);

            let mut client =
                radar_protocol::RadarChannel::new(100, Box::new(ws_transport));

            tracing::info!("Sending ping...");
            let now = Instant::now();
            match tokio::time::timeout(
                std::time::Duration::from_secs(5),
                client.ping(),
            )
            .await
            {
                Ok(Ok(_)) => {
                    println!("pong {}ms", now.elapsed().as_millis());
                }
                Ok(Err(e)) => tracing::error!("Ping failed: {:?}", e),
                Err(_) => tracing::error!("Ping timed out after 5 seconds"),
            }
            tracing::info!("Client completed");
        }
    };
}

JetStream Iroh

Iroh is a peer-to-peer networking library that provides NAT traversal, hole punching, and relay fallback. JetStream integrates with Iroh to enable peer-to-peer RPC communication.

Features

  • NAT Traversal: Automatic hole punching for direct peer-to-peer connections
  • Relay Fallback: Falls back to relay servers when direct connection isn’t possible
  • Discovery: Uses JetStream’s discovery service at discovery.jetstream.rs
  • ALPN-based Protocol Negotiation: Each service defines its own protocol version

Example

Here’s a complete example of an echo service using Iroh transport:

#![cfg(feature = "iroh")]
use crate::echo_protocol::{EchoChannel, EchoService};
use jetstream::prelude::*;
use jetstream_macros::service;
use okstd::prelude::*;

#[service(tracing)]
pub trait Echo {
    async fn square(&mut self, ctx: Context, i: u32) -> Result<String>;
}

#[derive(Debug, Clone)]
struct EchoServer;

impl Echo for EchoServer {
    async fn square(&mut self, _ctx: Context, i: u32) -> Result<String> {
        Ok((i * i).to_string())
    }
}

#[okstd::main]
async fn main() {
    // Initialize tracing subscriber
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::DEBUG)
        .with_thread_ids(true)
        .with_span_events(
            tracing_subscriber::fmt::format::FmtSpan::ENTER
                | tracing_subscriber::fmt::format::FmtSpan::EXIT,
        )
        .init();
    // Build the server router with the echo service
    let router = jetstream_iroh::server_builder(EchoService {
        inner: EchoServer {},
    })
    .await
    .unwrap();

    // get our own address. At this point we have a running router
    // that's ready to accept connections.
    let addr = router.endpoint().node_addr();

    // Build client transport and connect
    let transport = jetstream_iroh::client_builder::<EchoChannel>(addr)
        .await
        .unwrap();

    let mut ec = EchoChannel::new(10, Box::new(transport));
    for i in 0..10 {
        let b = ec.square(Context::default(), i).await.unwrap();
        println!("square response: {i} * {i} = {b}");
    }

    router.shutdown().await.unwrap();
}

Server Setup

To create an Iroh server, use the server_builder function:

#![allow(unused)]
fn main() {
use jetstream_iroh::server_builder;

let router = server_builder(EchoService { inner: EchoServer {} })
    .await
    .unwrap();

// Get the node address to share with clients
let addr = router.endpoint().node_addr();
}

Client Setup

To connect to an Iroh server, use the client_builder function:

#![allow(unused)]
fn main() {
use jetstream_iroh::client_builder;

let mut transport = client_builder::<EchoChannel>(addr)
    .await
    .unwrap();
}

Discovery

JetStream uses a custom discovery service for Iroh nodes. The discovery URL is:

https://discovery.jetstream.rs

This allows nodes to find each other using their public keys without needing to exchange IP addresses directly.

Feature Flag

To use Iroh transport, enable the iroh feature in your Cargo.toml:

[dependencies]
jetstream = { version = "10", features = ["iroh"] }

For more details, see the jetstream_iroh API documentation.

🦀 Crates

For detailed API documentation of all crates in this repository, please see the rustdoc documentation.

The main crates include:

  • jetstream - The main crate with the jetstream::prelude module
  • jetstream_client - Client implementation
  • jetstream_server - Server implementation
  • jetstream_wireformat - Encoding and decoding logic
  • jetstream_macros - Procedural macros
  • jetstream_rpc - RPC framework core
  • jetstream_9p - 9P protocol implementation
  • jetstream_ufs - UFS (Unix File System) implementation
  • jetstream_quic - QUIC transport
  • jetstream_iroh - Iroh transport
  • jetstream_websocket - WebSocket transport

📦 jetstream

📦 jetstream_9p

📦 jetstream_cloudflare

📦 jetstream_error

📦 jetstream_iroh

📦 jetstream_libc

📦 jetstream_macros

📦 jetstream_quic

📦 jetstream_rpc

📦 jetstream_ufs

📦 jetstream_websocket

📦 jetstream_wireformat

Changelog

12.1.0 (2026-01-24)

Features

  • publish npm package to gh (9b332b9)

Bug Fixes

  • Change git user configuration in workflow (c3d92c1)

12.0.0 (2026-01-24)

⚠ BREAKING CHANGES

  • add multiplexing ability to client.

Features

  • add multiple tag pool backends (c85aafb)
  • add multiplexing ability to client. (91a238e)
  • use tag pool in mux (cd5dd5d)

Bug Fixes

  • benchmarks code (c0d0f59)
  • delete release-plz (a7e3199)
  • lint errors and rm unnecessary compiler_error (27aed1e)
  • make TagPool use a channel (beb6209)
  • semaphor should use permit.forget() (340323c)

11.1.0 (2026-01-21)

Features

  • add prost_wireformat macro (beeb947)
  • add wireformat for SystemTime (169f74a)
  • prost_wireformat: make derives optional (12dfacb)

11.0.0 (2026-01-20)

⚠ BREAKING CHANGES

  • make error types more isomorphic
  • move quic and webocket to their own crates.
  • use more futures
  • fix proken publish
  • splits up packages
  • move modules to sensible parents
  • protocol -> coding
  • merge all the creates

Features

Bug Fixes

Code Refactoring

  • merge all the creates (faa0a1a)
  • move modules to sensible parents (4eba5fb)
  • protocol -> coding (5f86bc7)

10.1.0 (2026-01-20)

Features

Bug Fixes

  • benchmarks (af695e2)
  • cargo publish workspace (8db9367)
  • cleanup code and remove unused mermaid (c8975d5)
  • mdbook-changelog version issue (7043b8e)
  • move term-transcript to dev, gate s2n windows (5fa7f4c)
  • publish script (e8685cc)

10.0.0 (2025-11-19)

⚠ BREAKING CHANGES

  • make error types more isomorphic

Bug Fixes

  • make error types more isomorphic (aee2fa2)

9.5.0 (2025-10-30)

Features

  • add cleanup code serverside. add cloudflare docs to mdbook (91da99c)
  • introduce jetstream cloudflare module. (6e8cc01)

Bug Fixes

  • add comment about cf exec model (c979856)
  • remove tracing from sink and stream (97ac0a5)
  • remove unsafe code (a286d93)

9.4.2 (2025-10-28)

Bug Fixes

9.4.1 (2025-10-17)

Bug Fixes

  • remove redundant io imports and use fully qualified paths (7de4b9e)
  • target os cfg attrs (16e5c84)

9.4.0 (2025-10-15)

Features

Bug Fixes

  • cargo toml version issues (3481015)
  • collections can only be u16::MAX (6ada71a)
  • recursive self call (c51d455)
  • wasm32 feature gates (755f9c1)

9.3.0 (2025-10-14)

Features

9.2.0 (2025-10-05)

Features

  • dt features, remove rustdoc_to_md_book (0398159)

Bug Fixes

  • iroh example needs -F iroh (5246fb2)
  • wasm-pack build error. rm rustdoc2mdbook (68076cc)

9.1.2 (2025-10-05)

Bug Fixes

9.1.1 (2025-10-05)

Bug Fixes

  • benchmarks and add iroh_benchmarks (56dbc12)
  • hide documentation for iroh (47b104d)

9.1.0 (2025-10-02)

Features

  • introduce iroh examples (86e001f)

Bug Fixes

  • add support for libc in windows and mac (1fb3b5b)
  • disable running echo on windows (828d6be)
  • disable running echo on windows (7f44956)

9.0.0 (2025-09-29)

⚠ BREAKING CHANGES

  • move quic and webocket to their own crates.

Features

  • move quic and webocket to their own crates. (7d0ba9f)

Bug Fixes

  • simpler workflows for github actions (17185dd)

8.3.1 (2025-06-06)

Bug Fixes

8.3.0 (2025-05-31)

Features

8.2.1 (2025-05-29)

Bug Fixes

8.2.0 (2025-05-29)

Features

  • jetstream distributed features (52b5e89)

Bug Fixes

  • Update lib.rs for extern crates (ffb6777)

8.1.5 (2025-04-05)

Bug Fixes

8.1.4 (2025-04-04)

Bug Fixes

8.1.3 (2025-04-04)

Bug Fixes

  • extern async_trait and trait_variant and lazy_static (71e93e2)
  • extern_more (1bd58d8)

8.1.2 (2025-02-15)

Bug Fixes

  • make websocket pub again (21acf4b)

8.1.1 (2025-02-15)

Bug Fixes

8.1.0 (2025-02-15)

Features

  • add websocket transport (3f4054c)
  • channels can now be split (ef646a5)

8.0.10 (2025-02-14)

Bug Fixes

8.0.9 (2025-02-14)

Bug Fixes

8.0.8 (2025-02-01)

Bug Fixes

8.0.7 (2025-01-30)

Bug Fixes

8.0.6 (2025-01-30)

Bug Fixes

8.0.5 (2025-01-30)

Bug Fixes

  • use cargo publish workspace (e28a0f7)

8.0.4 (2025-01-30)

Bug Fixes

8.0.3 (2025-01-30)

Bug Fixes

8.0.2 (2025-01-30)

Bug Fixes

  • criterion benchmark test, framed implementation (25b1611)
  • failing serde tests (81db0de)
  • reenable sccache (757bb7e)
  • service macro works correctly with client calls (eb1fd0f)
  • snapshots for macros (fab686d)

8.0.1 (2025-01-28)

Bug Fixes

8.0.0 (2025-01-27)

⚠ BREAKING CHANGES

  • use more futures

Features

Bug Fixes

7.4.0 (2025-01-18)

Features

  • jetstream_rpc supports wasm (e97e6ca)

7.3.0 (2025-01-17)

Features

7.2.1 (2024-12-10)

Bug Fixes

  • keep reciver types as is in generated code (7d95671)

7.2.0 (2024-12-09)

Features

7.1.2 (2024-12-06)

Bug Fixes

7.1.1 (2024-11-25)

Bug Fixes

  • broken use statement for async_trait (cce4df6)

7.1.0 (2024-11-25)

Features

  • added async_trait support service macro (9a86185)

7.0.4 (2024-11-23)

Bug Fixes

7.0.3 (2024-11-21)

Bug Fixes

7.0.1 (2024-11-21)

Bug Fixes

7.0.0 (2024-11-21)

⚠ BREAKING CHANGES

  • fix proken publish

Features

6.6.2 (2024-11-21)

Bug Fixes

6.6.1 (2024-11-20)

Bug Fixes

6.6.0 (2024-11-20)

Features

  • distributes jetsream (d1477d5)
  • jetstream_distributed: placement (8a93788)

Bug Fixes

6.5.0 (2024-11-20)

Features

Bug Fixes

6.4.2 (2024-11-18)

Bug Fixes

6.4.1 (2024-11-11)

Bug Fixes

  • make the proto mod same vis as trait (a43c0a2)

6.4.0 (2024-11-10)

Features

  • Add support for bool in WireFormat (640c6ca)
  • Add tests for jetstream modules (18462d9)

Bug Fixes

6.3.4 (2024-11-10)

Bug Fixes

6.3.3 (2024-11-10)

Bug Fixes

  • update 9p to use trait_variant (96db410)

6.3.2 (2024-11-10)

Bug Fixes

6.3.1 (2024-11-09)

Bug Fixes

6.3.0 (2024-11-09)

Features

Bug Fixes

6.2.0 (2024-11-08)

Features

  • add i16,i32,i64,i128 types (3f0751a)

6.1.0 (2024-11-08)

Features

6.0.2 (2024-11-08)

Bug Fixes

6.0.1 (2024-11-08)

Bug Fixes

6.0.0 (2024-11-07)

⚠ BREAKING CHANGES

  • splits up packages
  • move modules to sensible parents
  • protocol -> coding
  • merge all the creates

Features

Bug Fixes

Code Refactoring

  • merge all the creates (faa0a1a)
  • move modules to sensible parents (4eba5fb)
  • protocol -> coding (5f86bc7)

5.4.2 (2024-11-07)

Bug Fixes

5.4.2 (2024-11-07)

Bug Fixes

5.4.1 (2024-11-07)

Bug Fixes

5.4.0 (2024-11-07)

Features

5.3.0 (2024-10-23)

Features

Bug Fixes

5.2.3 (2024-10-10)

Bug Fixes

5.2.2 (2024-10-07)

Bug Fixes

  • revert serde_bytes to bytes with serde (2e02460)

5.2.1 (2024-10-06)

Bug Fixes

  • wireformat: from_bytes doesn’t require a mutable buf (437c35c)

5.2.0 (2024-10-06)

Features

  • use serde_bytes::ByteBuf instead of Bytes (a1101d9)

Bug Fixes

5.1.4 (2024-10-03)

Bug Fixes

5.1.3 (2024-10-03)

Bug Fixes

5.1.2 (2024-10-03)

Bug Fixes

5.1.1 (2024-10-03)

Bug Fixes

5.1.0 (2024-10-03)

Features

Bug Fixes

5.0.0 (2024-10-03)

⚠ BREAKING CHANGES

  • splits up packages

Features

Bug Fixes

4.0.0 (2024-10-01)

⚠ BREAKING CHANGES

  • move modules to sensible parents

Code Refactoring

  • move modules to sensible parents (4eba5fb)

3.0.0 (2024-03-30)

⚠ BREAKING CHANGES

  • protocol -> coding
  • merge all the creates

Features

Bug Fixes

Code Refactoring

2.0.2 (2024-03-30)

Bug Fixes

2.0.1 (2024-03-29)

Bug Fixes

  • macros: protocol macro fix to spread fn args (b261a28)

2.0.0 (2024-03-29)

⚠ BREAKING CHANGES

  • protocol -> coding

Code Refactoring

1.1.1 (2024-03-29)

Bug Fixes

1.1.0 (2024-03-29)

Features

  • macros: service macro to remove boilerplate code (e0a9295)

1.0.0 (2024-03-25)

⚠ BREAKING CHANGES

  • merge all the creates

Code Refactoring

0.6.0 (2024-03-21)

Features

0.5.1 (2024-03-15)

Bug Fixes

  • filesystem under feature flag, rm newline (de4cf79)
  • Update client_tests.rs (4c50132)

0.5.0 (2024-03-15)

Features

  • rust-clippy code scanning (3dfb39f)

Bug Fixes

  • update to v2 upload sarif (e38bacb)

0.4.0 (2024-03-14)

Features

0.3.2 (2024-03-14)

Bug Fixes

0.3.1 (2024-03-14)

Bug Fixes

0.3.0 (2024-03-14)

Features

0.2.0 (2024-03-14)

Features