Capacity and admission control
Admission is decided on load. Every worker reports its one-minute load per core and the calls it holds, and ring refuses not_ready when every live worker is above WORKER_BUSY_LOAD — 0.85, the same figure the worker gives LiveKit as its own threshold, so the gate and the dispatcher agree. A worker reporting no load is treated as free, deliberately.
One number, agreed on both sides#
There are two places a call can be turned away: Connect's own admission gate, which decides whether to ring at all, and the dispatcher, which decides which worker gets a room. Giving them different thresholds produces the worst possible behaviour — a gate that admits a call the dispatcher then has nowhere to put — so the worker publishes 0.85 as its load_threshold and ring refuses above the same value.
The measure is one-minute load per core, not a call count. A worker holding three conversations on a large machine may be less loaded than one holding a single call on a small one, and a count would rank them wrongly. The calls held are reported too, but as context rather than as the decision.
heartbeat -> { load_per_core: 0.41, calls_held: 2 }
admission : refuse `not_ready` when every live worker reports load_per_core > 0.85
dispatcher : same 0.85, published by the worker as load_thresholdThe deliberate soft spot#
A worker that reports no load at all reads as free. That is a conscious trade rather than an oversight: an old or partially broken worker whose load figure never arrives would, under the strict reading, make the whole fleet look busy and turn away every caller. Refusing real calls on the strength of one process's silence is worse than the saturation the threshold guards against.
The failure that silence *is* allowed to cause is handled elsewhere and more directly: a fleet with nothing checked in for 90 seconds is refused outright, before a row exists. So silence from one worker is optimistic, and silence from all of them is decisive.
What saturation does to a caller#
| Who | What they see |
|---|---|
| The caller | The call is not answered. There is no apologetic message, because Connect never picked up |
The calls list | Nothing — admission refuses before a row exists |
| Needs You | A line-health finding: a fleet with no capacity left, which drains by itself when capacity returns |
| The follow-up drain | A line that is not ready, so the phone follow-up is retried in an hour instead of being burnt |
| The Owner's usage view | Nothing charged, because no call was held |
The asymmetry between the first two rows is the operational point of this page. Saturation is invisible in the call record precisely because the call never became a record, so a workspace measuring only calls will see a quiet hour rather than a rejected one. Line health exists to make that hour visible.
Sizing a fleet#
Count concurrent calls at your busiest hour, not calls per day.
Result Concurrency is what capacity is spent on; volume is not.
Leave room for the drain window. During a deploy, part of the fleet is finishing calls and taking no new ones for up to 180 seconds.
Result A fleet sized exactly to peak refuses calls every time it is updated.
Watch for
not_readyand for line-health findings rather than for slow calls.Result Capacity problems show up as absence — refusals before a row — while slowness shows up in
turn_timing. They are different faults with different fixes.Treat a rise in
not_reachedoutcomes as a capacity or dispatch signal.Result Past the failure threshold inside the health window, calls that never rang raise the finding for you.
One more constraint belongs in the sizing arithmetic: a call can run up to 30 minutes, the product's own MAX_CALL_SECONDS ceiling. A line whose conversations regularly approach that holds capacity far longer per caller than a line answering quick enquiries, and the two cannot be sized by the same rule of thumb.
Questions#
Why not just count calls per worker?
Because calls are not equal and machines are not equal. Load per core measures what the process is actually doing on the hardware it is actually running on, which is the quantity that decides whether the next call will be answered well or badly.
Can I raise the threshold above 0.85?
It is a configured value, but raising it on one side only breaks the agreement between admission and the dispatcher — the gate would admit calls the dispatcher will not place. The figure is shared for that reason, and a change has to be a change to both.
A caller says it rang and rang. Was that capacity?
It can be. Ringing that reaches nothing is what a refusal before a row looks like from outside, whether the cause is a saturated fleet or no worker checked in. Line health separates the two, and neither leaves a call record to inspect.