Index ¦ Archives ¦ Atom

Various Options To Deliver Real Time Notifications

If you wish to deliver (or) push data from your web server to your web application running in a browser in real time, you have 4 options at the time of writing this post (2022).

  1. Polling / Long Polling.
  2. Server Sent Events (SSE).
  3. Websockets.
  4. WebPush

Polling

Polling and Long Polling has been used traditionally & being used till date. As the name suggests polling / long polling is not push, but clients checking (a.k.a polling) every once in a while if something has changed in the server side. For example, client making a HTTP request to server every 10 seconds as an XMLHttpRequest (XHR) or more commonly known as AJAX (Asynchronous Javascript and XML).

But this is not efficient because it adds an unwanted load to the server. Imagine, 100 people using the website and each of them polling the server every 10 seconds. Even when there is no change in the server, it has to respond to every HTTP request made by the client & client has to keep polling.

Long Polling

Long polling is a better version of simple polling. Long polling is when client makes a HTTP request to the server and instead of immediately returning any response, the server holds the request until any data is available to send to the client. Once the data is delivered to the client, the client immediately makes another HTTP request and the cycle goes on. This approach is also called as Comet approach.

Server Sent Events

The Server Sent Events (SSE) is the first effort to push or stream data from server to the client. As usual the client makes the first request to server, the server holds the connection & uses some of the HTTP response headers to stream the data in the single connection, until the connection is closed by the server or client.

The main difference between long polling and SSE is that in long polling when server sends the response the HTTP request-response cycle ends & a new connection is opened again. i.e a new connection for every message. With SSE, only one connection is opened and the server keeps pushing the data.

The way it is achieved is through the "Transfer-Encoding: chuncked" response header. This header informs the client that the response size is unknown and the data will be sent in chunks. This method is usually used to transfer large files from the server to client. SSE takes advantage of this and defines a message format. The message format must have "data" field and optional "event", "id" and "retry" fields. Web browsers implement the EventSource javascript API to initiate a SSE request to server.

SSE is still HTTP request-response cycle, but everything happens within one request-response cycle. One of the main limitation, I see in SSE is the inability on the client side to set custom request headers. Lack of this ability means, one cannot pass authentication related headers as we do in usual HTTP request.

Websockets

Then came the websockets. If SSE is unidirectional (i.e servers streams events to the client), then websockets are bidirectional. Websockets is not HTTP. It is a new protocol altogether, similar to HTTP on layer 7. HTTP is used only for the initial handshake and if the server responds with an Upgrade response header, then a websocket connection is established between the client & the server. Web browsers implement the WebSocket API to initiate a websocket connection from client to server.

Once a websocket connection is established, each side can exchange data with each other. For pushing data from server to client, the server can ignore any message that is sent by client keep pushing the data.

WebPush

WebPush is relatively new compared to all the above. Similar to SSE, WebPush is also unidirectional. It is ideal to push notifications from server to client. The notifications are then rendered as a notification of the Desktop Environment of the OS in use. This also involves additional steps to implement compared to the above methods. WebPush can deliver notifications even when the webpage is not loaded.

For WebPush, browsers are responsible to implement Push API in browsers & a online service to receive push notifications from our servers. For example, a service called autopush is used by Firefox and Firebase cloud-messaging is used by Chrome derivates.

On the client side, WebPush requires ServiceWorkers which are code that runs asynchronously in the background when the browser is open & the ServiceWorker alone can access the Push API to subscribe to our server.

On the server side, we need to provision atleast 3 endpoints.

  1. A GET request to get cryptographic keys from server.
  2. A POST request to subscribe for notification from client side.
  3. A POST request to publish notification to the online service run by the browser.

In short, when you use WebPush, you rely on a third party service to deliver your notification to the respective browser and for this reason, the notification messages are end-to-end encrypted with the public-key cryptography.

Final Notes

There is no one best method. One need to carefully consider which of the above methods are suitable for them based on the needs & the system design.

© Prasanna Venkadesh. Creative Commons Attribution ShareAlike. Theme by Giulio Fidente on github.