How Many WebSocket Connections Fit on One Server?
Concurrent WebSocket connections per server are bound by memory and fan-out, not CPU. Learn the capacity math to size real-time infrastructure before you scale out.
A single modern server can hold hundreds of thousands of idle WebSocket connections. The number that stops you is almost never CPU and almost never the mythical 65,535 port limit. It is memory per connection and, above all, message fan-out. Idle connections are cheap; active broadcast is what costs you. If you do the capacity math on the right variables, you will know when you actually need a second box, which is usually much later than teams assume, and you will stop paying for horizontal scale you do not need yet.
The port limit is a myth, kill it first
The most common wrong answer is "a server can only handle 65,535 connections because that is the port range." That confuses source and destination ports. A server listens on one port; each accepted connection is identified by the tuple of client IP, client port, server IP, and server port. Millions of clients can connect to a single server port. The real ceilings are file descriptors and memory, both of which you tune.
Raise the file descriptor limit, tune the ephemeral port range on the client side of any proxies, and the OS will happily hold hundreds of thousands of sockets. This is table stakes and it is why the port myth needs to die before you plan capacity. If your provider or design is fighting you on this, that is one of the real-time backend mistakes that break apps at scale.
Memory is the real per-connection cost
Each connection carries a cost: the socket buffers, your per-connection application state, and any framework overhead. Depending on your stack, that ranges from a few kilobytes to tens of kilobytes per connection. Multiply by your target: 200,000 connections at 10 KB each is 2 GB just for connection state, before your application heap.
So the first capacity question is: what is your real per-connection memory footprint under your framework, with your state? Measure it, do not guess. Keep per-connection state lean, push heavy data to shared structures, and you fit far more per box. This is where the difference between a bloated framework and a tight one shows up, and it is why I care about what a real-time backend actually needs to be rather than whatever is fashionable.
Fan-out, not connection count, is what melts you
Here is the number that actually decides your architecture: messages sent per second, which is roughly connections times per-connection message rate. A hundred thousand idle connections cost you memory and almost no CPU. A hundred thousand connections each receiving 10 messages a second is a million sends per second, and that is where CPU, serialization, and network saturate.
So the honest capacity metric is not "how many connections" but "how many messages per second at peak fan-out." A chat room with 100,000 members where anyone can post is a fan-out bomb: one message becomes 100,000 sends. That is why scaling rooms, not connections is the right frame, and why sending deltas instead of full state directly buys you capacity: smaller payloads mean more sends per second on the same hardware.
Do the math before you shard
Work it backwards. Suppose you want to hold 300,000 concurrent users, each receiving on average 2 messages a second at peak. That is 600,000 sends per second and, at say 12 KB per connection, about 3.6 GB of connection memory. A well-tuned single node can plausibly carry that. Now suppose peak fan-out spikes to 20 messages a second during a live event: 6 million sends per second, and now you need multiple nodes with a pub/sub backplane carrying messages between them.
Notice the trigger for scaling out was fan-out, not connection count. Size for your peak send rate, keep headroom for the burst, and add nodes when the send rate, not the connection count, crosses what one box serves. And protect yourself from pathological clients with per-connection rate limits so one abuser cannot manufacture a fan-out spike.
Where a managed layer changes the math
Doing this yourself means tuning file descriptors, measuring per-connection memory, building the backplane, and load-testing peak fan-out. A purpose-built real-time platform like AltoHost handles the connection scaling and cross-node fan-out so your capacity planning is about your message rates, not your socket plumbing. When you compare options, evaluate the real-time backend on published fan-out throughput and per-connection overhead, because those are the numbers that decide your bill.
The takeaway is simple. One server holds far more connections than folklore claims. Memory sets your connection ceiling, fan-out sets your real ceiling, and CPU is rarely the wall. Measure both, size for peak sends, and scale out on message rate. For infrastructure that already solved the plumbing, AltoHost is where I would run the numbers.