{"record":{"id":"c7a082ec1bd6fc6a","repo":"n0-computer/iroh","slug":"the-relay-is-rate-limiting-this-endpoint-outbound","errorCode":null,"errorMessage":"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. Read more about rate limiting at https://docs.iroh.computer/relays/rate-limiting","messagePattern":"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\\. Read more about rate limiting at https://docs\\.iroh\\.computer/relays/rate-limiting","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"iroh-relay/src/protos/relay.rs","lineNumber":136,"sourceCode":"\n/// One-way message from server to client indicating issues with the relay connection.\n#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]\n#[non_exhaustive]\npub enum Status {\n    /// The connection is healthy and recovered from previous problems.\n    #[display(\"The connection is healthy and has recovered from previous problems\")]\n    Healthy,\n    /// Another endpoint connected with the same endpoint id. No more messages will be received.\n    #[display(\n        \"Another endpoint connected with the same endpoint id. No more messages will be received.\"\n    )]\n    SameEndpointIdConnected,\n    /// The relay is rate-limiting traffic received from this endpoint.\n    ///\n    /// Sent once per connection when the relay first throttles reading from the client.\n    #[display(\n        \"The relay is rate-limiting this endpoint; outbound relay traffic is being throttled. \\\n        Send less data over the relay, or, if you operate this relay, raise Limits::client_rx. \\\n        Read more about rate limiting at https://docs.iroh.computer/relays/rate-limiting\"\n    )]\n    RateLimited,\n    /// Placeholder for backwards-compatibility for future new health status variants.\n    #[display(\"Unsupported health message ({_0})\")]\n    Unknown(u8),\n}\n\nimpl Status {\n    #[cfg(feature = \"server\")]\n    fn write_to<O: BufMut>(&self, mut dst: O) -> O {\n        match self {\n            Status::Healthy => dst.put_u8(0),\n            Status::SameEndpointIdConnected => dst.put_u8(1),\n            Status::RateLimited => dst.put_u8(2),\n            Status::Unknown(discriminant) => dst.put_u8(*discriminant),\n        }\n        dst","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/n0-computer/iroh/blob/2b4de030ce5e0133f272871a76f0c685c63f552a/iroh-relay/src/protos/relay.rs#L118-L154","documentation":"This is a relay health-status error from iroh-relay. The relay server is throttling traffic received from this client endpoint because it exceeded the configured receive limits (Limits::client_rx). Once throttling starts, data sent through the relay is delayed/dropped, so outbound relay traffic toward peers slows down.","triggerScenarios":"A client connected to an iroh relay sends data faster than the relay's client_rx rate limit allows. The relay emits this ClientHealth::RateLimited status once per connection when it first begins throttling reads from that client.","commonSituations":"Chatty applications that push large amounts of relayed (non-direct) traffic; many endpoints sharing one relay with per-client limits; operators who set Limits::client_rx too low for their workload; dev/test setups where heavy traffic intentionally flows over the relay instead of via direct connections.","solutions":["Reduce the volume/frequency of data sent over the relay; prefer direct (holepunched) connections so traffic bypasses the relay.","If you operate the relay, raise the client_rx limit in the relay's Limits configuration.","Check relay connectivity/latency and whether direct connection establishment is failing, forcing all traffic through the relay.","Back off and retry after throttling; the status is sent once per connection when throttling first begins."],"exampleFix":"// before: relay operator with default limits\nlet server = RelayServer::builder().bind(0.0.0.0:3340).await?;\n// after: raise per-client receive limit\nlet server = RelayServer::builder()\n    .bind(0.0.0.0:3340).await?\n    .client_rx(10_000_000)  // bytes/sec, raised from default\n    .spawn();","handlingStrategy":"retry","validationCode":"// No pre-call check possible; monitor client health statuses instead.\nfn handle_health(status: &ClientHealth) {\n    if matches!(status, ClientHealth::RateLimited) {\n        // enable backpressure: queue relayed sends, prefer direct connections\n    }\n}","typeGuard":"fn is_rate_limited(h: &ClientHealth) -> bool { matches!(h, ClientHealth::RateLimited) }","tryCatchPattern":"match result {\n    Ok(v) => v,\n    Err(e) if is_rate_limited_msg(&e) => schedule_backoff_and_retry(),\n    Err(e) => return Err(e),\n}","preventionTips":["Prefer direct (holepunched) connections over relayed traffic","Add client-side send throttling/queueing for relayed data","If you run the relay, size Limits::client_rx to expected per-client throughput","Watch relay health statuses and back off at the first RateLimited signal"],"tags":["network","rate-limit","relay","throttling"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"2b4de030ce5e0133f272871a76f0c685c63f552a","analyzedAt":"2026-09-08T04:26:47.755Z","contentChangedAt":"2026-09-08T04:26:47.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}