The Myth of Long Polling

Jonathan Gros-Dubois
Tech Renaissance
Published in
4 min readNov 7, 2016

Several years ago, developers had a good reason to feel uncomfortable about using plain WebSockets in production — The WebSockets protocol had gone through a number of iterations and many web browsers still had not implemented the WebSocket API. Back then, apps that needed to receive real-time notifications from a server had to resort to a number of ‘hacks’ to simulate the behavior of a long-lived/stateful real-time connection.

The most popular hack was ‘Long Polling’ — Long Polling basically involves making an HTTP request to a server and then holding the connection open to allow the server to respond at a later time (as determined by the server). In order for this trick to work effectively, a number of techniques need to be employed to make sure that no messages are missed; this might involve buffering messages on the server side and/or having multiple open HTTP connections to the server (for each client).

Although Long Polling works, it is very expensive in terms of CPU, memory and bandwidth. The chart below shows the bandwidth consumption differences between WebSockets vs Long Polling in a relatively common use case:

Pushing out a very short message every second from the server (source).

In addition to significantly higher resource requirements, at scale, Long Polling also introduces new architectural issues. Once you have more than one Long Polling process running on a single server, things tend to get ugly. Because HTTP is stateless, if you want to spread connections across multiple processes or hosts, you typically end up having to use a sticky load balancer (aka with session stickiness) to make sure that clients don’t get shifted around between different servers in the course of a single real-time session (which causes issues for a lot of use cases).

Sticky load balancing is often seen as being a hack on top of a hack because it introduces new problems of its own. These include:

  • It can cause uneven distribution of connections between processes/hosts (for example, with IP-based stickiness, clients from the same corporate network might all end up on the same process/host; leaving all other processes/hosts empty).
  • It allows malicious users to target and cripple specific hosts within your system (DoS/DDoS vulnerability) — With session stickiness, because the host selection is deterministic (and needs to happen for every inbound message), a malicious user can trick the load balancer into spamming a specific host and cause Denial of Service (bringing down one server at a time).

In spite of the significant performance and architectural issues mentioned above, people are still overwhelmingly using real-time libraries which rely on Long Polling fallbacks. A few years ago, the two main arguments against using plain WebSocket-based solutions were:

  1. Some older browsers do not support the WebSocket API.
  2. Some proxies block WebSocket connections — E.g. When using some 3G internet services or accessing the internet from inside a corporate network.

With the advent of evergreen browsers, most people will agree that #1 is no longer an issue; the WebSockets API is supported by practically all major web browsers.

The second issue, however, is still a problem in the minds of many developers; after all, it could be years, decades or maybe even centuries before some of these old corporate proxies get updated.

The good news is that #2 is really easy to get around; the solution is simply to serve your WebSockets over TLS (use wss:// instead of ws://). Based on all the testing I did and feedback I collected over the past 3 years as the main author of SocketCluster (which is 100% WebSockets-based; see µWebSockets), I have not yet witnessed a corporate proxy block encrypted WebSocket traffic.

The reason why wss:// traffic doesn’t get blocked is because when you create a WebSocket connection over TLS/SSL, any proxy which is sitting between your client and your server will only be able to see cipher-text. There is no reliable way for the proxy to differentiate between WSS traffic and regular HTTPS traffic when it’s all encrypted*.

In light of this information, and the fact that most web apps are moving to HTTPS anyway, I think that now is a good time to re-evaluate our options when it comes to building real-time apps and services.

* Note that there may be extreme cases where a company might install fake root certificates on their corporate workstations to snoop in on their employees’ internet usage (MitM) and it’s possible that in these cases the corporate proxy could still block encrypted WebSocket traffic.

--

--