#4724·livekit

send_side_bwe_pacer: "leaky-bucket" is defined but not wired — how to enable rate-based pacing of SFU egress?

Author: eilon-decartCreated Aug 4, 2026Updated Aug 4, 2026

Context: we run livekit-server as an SFU between browser publishers and server-side (libwebrtc) subscribers across inter-cloud paths (AWS↔GCP). We consistently measure direction-asymmetric micro-loss: legs where a libwebrtc endpoint sends (its pacer smooths frames) are clean, while SFU-forwarded legs show recurring NACK-recovered loss. In an isolated A/B on the same path (identical packets, line-rate frame bursts vs the same frames spread over ~8ms), a transient loss event hit the bursty shape ~90x harder (0.44% vs 0.007% cumulative), with endpoint sockets, qdiscs, and ENA counters all clean — i.e. the forwarder's line-rate write bursts appear to be what shallow queues on the path punish.

Code: a rate-based pacer exists but doesn't appear to be reachable:

  • pkg/sfu/pacer/pacer.go defines PacerBehaviorLeakybucket = "leaky-bucket" alongside pass-through / no-queue.
  • pkg/sfu/pacer/leaky_bucket.go implements it (NewLeakyBucket(logger, bwe, interval, bitrate)).
  • But the selection switch in pkg/rtc/transport.go (createPeerConnection / IsSendSide block, ~L573) only handles PacerBehaviorPassThrough and PacerBehaviorNoQueue; leaky-bucket falls into default:NewNoQueue. So congestion_control.send_side_bwe_pacer: leaky-bucket silently degrades to no-queue (and with use_send_side_bwe: false the pacer is unconditionally pass-through).

Questions:

  1. Is there a supported way to get rate-based pacing of downstream forwarding in current releases (we run v1.11.0, checked master too)?
  2. Is LeakyBucket considered production-ready, and is wiring it into the send_side_bwe_pacer switch planned / would a PR adding the missing case be welcome?
  3. Any known caveats that led to it being left unwired (latency under congestion, interaction with the stream allocator, etc.)?

Happy to share the measurement setup/data if useful.