Let’s talk about longpolling

golongpoll v1.1.0 released

The golang longpolling library that I maintain has a new release out today.  Check it out at:  https://github.com/jcuga/golongpoll

If you write applications in golang and need server-to-browser events, this library can make notifications and web pub-sub quite easy.  If you don’t, stick around and learn a little about longpolling.

What is longpolling?

Longpolling is a technique for sending server events to web clients.  This technique is unidirectional, sending events only from the server to the client.  Use cases include:

  • notifications (think facebook)
  • event streams
    • I’ve used longpolling to track networking events in some proxy/content-blocking software.  This was in fact the impetus for creating the golongpoll library.
  • general pub-sub
    • use longpolling for browsers to subscribe to server events, if browsers need to publish events, just make a normal HTTP handler in addition to longpolling.

For the nitty-gritty details about longpolling (and other server-push techniques), see the excellent answer to the StackOverflow question: What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?

Why longpolling?

Longpolling traditionally has a bad rap.  The technique is thought to be a bit of a hack and difficult to scale in production.  These opinions do have some truth to them, but these were issues mostly with web frameworks written in Java, Python, or PHP.  Each of these have their limitations to how HTTP requests are handled which makes longpolling expensive and clunky.  For example, in most Python web applications, the code is running in a WSGI container which has hard limitations on how long requests can last and there is a non-trivial amount of overhead in keeping each request open waiting on longpoll events.

Enter golang.  Go has a much different approach that allows for ultra-lightweight thread-like things called goroutines.  You can spin up thousands upon thousands of goroutines and keep them running for long periods of time on modern machines without breaking a sweat, especially if most of the goroutines are in a waiting state until an event occurs.  So many of the performance and scalability issues with other web platforms go away when using Go.

This leaves a number of advantages to using longpolling over other alternatives like websockets and Server-Sent Events:

  • longpolling is plain old HTTP, and is supported by even the oldest browsers.
    • Websockets is a completely separate protocol and only works on modern browsers.  Also being plain HTTP means no troubles moving through arbitrarily many proxies and infrastructure that may filter or modify content.  Also things like VPN web-clients (for example: Juniper SSL VPN / Pulse Connect products) will have an easier time digesting longpolling versus websockets.
  • longpolling can be very simple to implement on both  the client and server ends.  Just use my library 🙂
  • Easier debugging.  Just look at firebug/dev console in your browser and the HTTP logs on your webserver.  Longpolling traffic is just like any other web traffic.
  • Server-Sent Events is promising, but not supported by IE.

Even language and implementation details aside, I’m not alone in the opinion that longpolling isn’t all that bad.  Take a look at fanout blog’s Long-polling doesn’t totally suck

Why not longpolling?

There some reasons to consider something other than longpolling.  There are scenarios where websockets may be more appropriate, and the emerging HTTP/2 protocol will eventually negate the need for longpolling once HTTP/2 is widely adopted.

Reasons to chose websockets over longpolling include:

  • You need truly bi-directional data flow.
    • you could use longpolling for server-to-client and then a separate HTTP handler for client to server, but it may be a pain to wire the two streams of data together on the server side, or you might want the smallest delay possible in which case websockets is probably the better choice.
  • Your data isn’t discrete events.  Websockets is more appropriate when you’re sending more stream-like data.  Longpolling works better when you’re dealing with things like events or notifications.

Or perhaps you want to use HTTP/2 because:

And the winner is….

You tell me.  There is no hard-and-fast rule on when to use each of these technologies.  You’ll have to evaluate for yourself what best suits your needs, but you should give longpolling a fair consideration, especially if there are a lot of unknowns about older browsers or having to support traveling over a variety of different infrastructure (proxies, corporate firewalls, VPNs).

You should also consider the access methods that users employ to reach your application.  If they are using a VPN web-client or some other piece of weird software that heavily modifies traffic, then this may make or break your server-push traffic.  By the way, some of the fancier JavaScript frameworks break when using these special web-clients, but thats a topic for another day.  In case you’re scratching your head wondering what I’m talking about, take a look at these guides here and here that outline what can and can’t be done in JavaScript when using these tools.