v0.x

BBR-lite: congestion control in plain JavaScript

A small model-based congestion controller: estimate bottleneck bandwidth and minimum RTT, and size the window from their product.

Loss-based congestion control (Reno, CUBIC) treats packet loss as the signal that the network is full. BBR takes a different view: build a model of the path — how fast is the bottleneck, and how long is the round trip when queues are empty — and send at that rate.

The model in one line

javascript
const bdp  = bbr_btlbw * bbr_min_rtt;
const cwnd = clamp(
  2 * bdp,
  min_limit_bytes_in_flight,
  max_limit_bytes_in_flight   // safety net
);

bbr_btlbw is the maximum delivery rate seen over the last few round trips; bbr_min_rtt is the minimum RTT over the last ten seconds. Their product, the bandwidth-delay product, is exactly the amount of data the pipe can hold without building a queue.

Why "lite"

Full BBR cycles through startup, drain, probe-bandwidth and probe-RTT phases with carefully tuned gains. QUICO keeps the model and a simplified state machine: a startup phase that doubles until delivery rate stops growing, then steady pacing at the estimated rate with periodic probing. It is a fraction of the code and easy to instrument from JavaScript.

Pacing in an event loop

Sending at a rate means spacing packets out in time. In Node.js that means batching: we compute how many bytes the pacing budget allows since the last send, flush that many packets in one turn of the event loop, and schedule the next turn. Timers below a millisecond are not reliable, so the budget absorbs the jitter.

Congestion control is listed as in progress in the README; this post is the design we are converging on.

colocohen

Author of QUICO, LemonTLS and a family of pure-JavaScript network servers.