Hi everyone,
We’re self-hosting LiveKit and recently ran a company town hall expecting ~500 concurrent participants. Everything worked fine up to about 70 participants, but past that point users started getting disconnected on their own — no obvious error on our side, connections just dropped.
Hoping someone can point us in the right direction.
Our setup:
Self-hosted LiveKit (single server), Docker
Using SFU (media) + signaling on the same instance
WebRTC publishing/subscribing
Clients: mix of web and desktop apps
What we’ve checked so far:
No errors in server logs at the time of the drops
Server CPU/memory look fine
Ports are open; we’re not obviously hitting NAT/firewall limits
Participants drop one by one over a few minutes, not all at once
Questions:
Is there a participant/connection limit on a single LiveKit node that would cause this? Should we move to a distributed/cluster deployment for 500+ participants?
Any recommended config.yaml settings (turn config, media config, limits) we should verify?
Could this be a bandwidth/ICE issue, or something about how the SFU handles large rooms?
We can share logs/config if helpful. Any guidance would be appreciated.
@sahiti, There is no 70-participant cap in LiveKit. A single node benchmarks to thousands of subscribers. The livestreaming test ran 1 publisher to 3000 subscribers on one server (benchmark). So your 70 limit comes from the environment, not from LiveKit.
The likely cause is bandwidth, not CPU. LiveKit scalability is bound by CPU and bandwidth, and the docs advise 10 Gbps ethernet or faster for production (deployment). A town hall sends each speaker to every listener, so the outbound traffic grows with the participant count. Your CPU looks fine because the network card saturates first. When the uplink saturates, packets drop, ICE fails on the sustained loss, and users disconnect one by one. This matches your slow, one-by-one pattern.
A cluster will not fix a single large room. In a multi-node deployment, one room runs on one selected node (distributed). Extra nodes spread different rooms across the cluster. They do not split one 500-person room. So for this town hall you need one node with more bandwidth, not more nodes. A cluster helps later, when you run many rooms at once.
Check these next:
Measure the server network egress during the event, not just CPU. The egress number shows you if the uplink saturated.
Confirm the full RTC UDP port range is open end to end. A blocked range forces clients onto TURN relay, and that relay runs on the same box, so it doubles the load.
Raise the container file-descriptor limit. Each participant uses several sockets, and the Docker default of 1024 can run out and drop connections with no clear error.
# livekit.yaml: the media UDP range must be fully open on the firewall
rtc:
port_range_start: 50000
port_range_end: 60000