Post

How do websites/apps know that you got a new Notification?

How does Gmail know that you got an email without you refreshing the page? Or how does Instagram know instantly that you got a follower request? Generally, there are two approaches: client pull or server push.

The Naive Way — Short Polling (Client Pull)

Every 10 seconds or so, we send a request (poll) to the server to check for updates. The pros is that server resources are freed almost immediately for each request the moment we send back a response.

However, this can be expensive for the server as:

  • The number of requests are high, generates a lot of traffic
  • Updates are not instantaneous

Thus, client short polling is generally not used in the industry.

Long Polling (Client Pull)

The idea is that instead of the client constantly polling the server, we want the server to push data to the client as soon as an update happens. However, servers can’t randomly push data to clients as clients don’t listen on an open port and accept incoming connections. So, we need to keep a persistent connection initiated by the client.

This is based on Comet, and how it works is that you open a request to the server and wait for its response for a long period of time. The server intentionally does not respond right away, but waits until a notification arrives then responds. In order to keep the connection alive, client and server do need to send an occasional packet to each other.

There are a few minor problems to note, mainly:

  • Timeouts (Connection gets closed by the proxy server if it remains idle for too long)
  • Each thread is blocked till a response is made for php/apache (however, any async approach like Node solves this problem)

Below is a diagram that illustrates how both of these work.

Short vs Long Polling

For iOS, this is done through Apple’s servers, so that the phone only has a single persistent connection to Apple’s servers, and then as a developer we proxy notifications through their servers to the client.

For Android, we can use Firebase Cloud Messaging as a centralised service at no cost.

The above models were sufficient for early web applications, because early websites were only displaying static content. But as the web evolved, the need arose to allow servers send data to clients without a client requesting it first. This led to server push technology in the 2000s.

As the HTTP request-response model was not designed for these use cases, different mechanisms were invented. These mechanisms are WebSockets and server-sent events (SSE).

WebSockets (Server Push)

A WebSocket is just a persistent connection between the client and server. It features full-duplex communication channels over a single TCP connection.

This has lower overhead than half-duplex alternatives like the above mentioned client polling, and facilitates real-time data transfer from and to the server. As such, we don’t need to poll the server whenever we want to receive a real-time response.

Some libraries like Socket.IO actually have an hierarchy of their own, meaning that it will do client long/short polling when WebSocket fails.

Server-Sent Events (Server Push)

Unlike WebSockets which has their own protocol, SSEs are transmitted over HTTP and are unidirectional. After an HTTP connection has been established between the server and the client, the server can send automatic updates.

Think of SSEs as a long-running HTTP request that notifies the client whenever the server has an update. SSEs are designed to be more efficient than long polling, and have features such as automatic reconnection, event IDs, and the ability to send arbitrary events.

In a nutshell, for when to use each:

Short Polling: Never.
Long Polling: Simple to implement, go-to when you don’t need too complex solutions
WebSockets: Mainly for games, not as robust for scenarios like guest wifi networks or firewalled intranets where sockets might fail and only HTTP can get through
Server-Sent Events: Use when you need the efficiency or scalability

Resources:

This post is licensed under CC BY 4.0 by the author.