diff --git a/docs.json b/docs.json index ddee18f..43444a1 100644 --- a/docs.json +++ b/docs.json @@ -96,7 +96,8 @@ "pages": [ "deployment/dedicated-infrastructure", "iroh-services/relays/public", - "iroh-services/relays/managed" + "iroh-services/relays/managed", + "relays/rate-limiting" ] }, { diff --git a/relays/rate-limiting.mdx b/relays/rate-limiting.mdx new file mode 100644 index 0000000..5e749f8 --- /dev/null +++ b/relays/rate-limiting.mdx @@ -0,0 +1,105 @@ +--- +title: "Rate Limiting" +description: "How relays throttle traffic per connection, and how to configure limits on a self-hosted relay" +--- + +## Why you're here + +If an iroh endpoint just logged something like this: + +``` +The relay is rate-limiting this endpoint; outbound relay traffic is being +throttled. Send less data over the relay, or, if you operate this relay, +raise Limits::client_rx. +``` + +it means the relay your endpoint is currently routed through has started +throttling how fast it reads data from your connection. This is not an error. +This just means that the connection stays open and traffic keeps moving, just +slower than usual. + +Two ways to fix it: + +- **Get a direct connection instead.** Relay rate limits only apply while traffic is relayed. A successful direct P2P path bypasses the relay entirely. If two endpoints keep falling back to the relay, see [diagnose a direct connection](/iroh-services/net-diagnostics/quickstart). +- **Use a relay with a higher limit.** [Shared relays](/iroh-services/relays/shared) and [dedicated relays](/iroh-services/relays/managed) both allow more throughput than the public relays. If you run your own relay, raise or remove its limit — see [Self-hosted relays](#self-hosted-relays) below. + +This notice is sent at most once per connection, and only to endpoints at iroh +version 1.0.4 or higher. Older clients are throttled the same way but won't see +the warning. + +## Public relays + +The [public relays](/iroh-services/relays/public) n0.computer runs are free, +open to every iroh endpoint, and rate-limited to prevent abuse of shared +infrastructure. + +The exact thresholds aren't published, as they get tuned as needed. However, the +mechanism is applied per connection. If you are using the N0 preset, you're +sharing the relay's total capacity with every other tenant, so heavy traffic +from other users can affect your experience even before your own connection hits +its individual limit. + +Public infrastructure is meant for development and hobby use. + +## Shared and managed relays + +[Shared relays](/iroh-services/relays/shared) run on separate infrastructure +from the public relays, with far fewer tenants per machine and higher +per-connection limits. + +[Dedicated relays](/iroh-services/relays/managed) provisioned through Iroh +Services are dedicated to your project — no other tenants, no rate limits at +all. + +## How it works + +Rate limiting is a property of a single relay *connection*, not a global switch. + +Each client connection gets its own token-bucket limiter on the side of the +relay that reads data sent by that client (`rx`, for "receive"): + +- **`bytes_per_second`** — the steady-state rate the relay will keep reading from that connection. +- **`max_burst_bytes`** — how far a client can exceed that rate momentarily before the bucket runs dry. + +When a client's bucket empties, the relay stops reading from that connection's +socket until it refills. Data isn't dropped — the client just experiences +backpressure: writes to the relay stall until the bucket has room again. This is +what triggers the one-time `RateLimited` status notice. + +Because the limiter is per-connection, one client hitting its limit doesn't affect any other client on the same relay. + +## Self-hosted relays + +If you run the `iroh-relay` binary (or embed the `iroh-relay` server crate) +yourself, rate limiting is **off by default**. This means connections can send +unlimited data. + +With the `iroh-relay` binary, configure it in your TOML config file: + +```toml +[limits.client.rx] +bytes_per_second = 1_000_000 +max_burst_bytes = 2_000_000 +``` + +`bytes_per_second` is required to enable the limiter; `max_burst_bytes` is +optional and defaults to no burst allowance above the steady rate if omitted. + +If you're embedding the relay server as a library, the equivalent is +`iroh_relay::server::Limits::client_rx`. This is the field the client-facing +warning message refers to when it says "raise `Limits::client_rx`". + + +`Limits` also has `accept_conn_limit` / `accept_conn_burst` fields for rate-limiting new incoming connections. As of this writing they're reserved but not yet enforced — setting them has no effect. + + +Consider a per-connection limit even on a single-tenant dedicated relay: it protects your egress bandwidth and CPU from a single misbehaving client or a bug in your own application, not just from other tenants. + + +## See also + +- [Public Relays](/iroh-services/relays/public) +- [Shared Relays](/iroh-services/relays/shared) +- [Managed Relays](/iroh-services/relays/managed) +- [Dedicated Infrastructure](/deployment/dedicated-infrastructure) +- [Relay source (`iroh-relay`)](https://github.com/n0-computer/iroh/tree/main/iroh-relay)