Published on

Method of Real-Time Communication

TL;DR

  • Websocket: 2 ways communication (chat, gaming, collaboration,..)
  • SSE: one-way communication (server -> client), ideal for notification, live feed,...
  • Polling: easiest to implementation but inefficient at scale.

Problem

You're understand the HTTP request and wanna building a realtime feature like chat, notification, live,... but the HTTP request restrict you to do that. The real-time communication can help to solve these problem.

But there're a lots of method to implement

Should I use Websocket, SSE or Polling to my business?

Choosing a wrong mechanism lead to:

  • redundance workload to solve the simple things
  • inefficient cost
  • slow your app

Intuition

Thinking communication are:

  • Polling: messaging someone repeatedly to ask anything new?
  • SSE: messaging someone let me know if you have anything new? and they will message to you back whenever they have a new things.
  • Websocket: Staying on a live call, you're video call to someone and you will know whenever they have a new things and they also know your new things.

Solution Overview

There're 3 common approaches:

MethodDirectionRealtimeComplexityUse Cases
PollingClient -> ServerSimpleSimple dashboard, delayed notification,..
SSEServer -> ClientMediumNotification, live update,...
WebsocketBoth directionsHardStreaming, chats, game, collaboration, ...

Deep Dive

Polling

The client repeatedly sends requests by wrap them into the setInterval function:

// this function run every 3s from Frontend
setInterval(async () => {
  const res = await fetch('/api/messages')
  const data = await res.json()
  updateUI(data)
}, 3000)

SSE - Server-Sent Events (SSE)

The server send event to the client whenever they have an updated:

const eventSource = new EventSource('/events')

eventSource.onmessage = (event) => {
  console.log(event.data)
}

Websocket

Websocket is the two ways connection from server and client. It has a persistent connection from server and client, whenever they have updates, the update will be sent to others.

Server connection

Understand this like the SSE. Sometime you need to send the update for the concurrent user like hunt for discount, have a new feeds, real-time dashboard (delivery tracking, revenue,...),...

Thinking that you need to update to their client about newest information instead of waiting for the new refresh.

const WebSocket = require('ws')

const wss = new WebSocket.Server({ port: 3000 })

wss.on('connection', (ws) => {
  console.log('Client connected')

  // send to client
  ws.send('Hello from server')

  // receive from client
  ws.on('message', (message) => {
    console.log('Received:', message.toString())
  })

  // ... adding more listening message

  // close connection trigger
  ws.on('close', () => {
    console.log('Client disconnected')
  })
})

Client connection

Proactive checking a new data. user request when they have something to update or exchange with server or partner in the system.

User A send a message to user B and that's important message. It would be instantly send to user B without waiting to refresh (user B don't know when user A message to him). At this case, server proactively send message to user A.

const ws = new WebSocket('ws://localhost:3000')

ws.onopen = () => {
  console.log('Connected to server')
}

// listen from Server
ws.onmessage = (event) => {
  console.log('Server says:', event.data)
}

// ... adding more listening message here

// close connection trigger
ws.onclose = () => {
  console.log('Disconnected')
}

// send to server
function sendMessage() {
  const input = document.getElementById('msg')
  ws.send(input.value)
  input.value = ''
}

Trade-offs

Polling

Pros

  • Easy to implement

Cons

  • Wastes resources (many empty requests)
  • Not truly real-time
  • DDoS (accidentally by multiple user at the time)
  • Need handle caching on Server

SSE

Pros:

  • Efficient for update from server to client
  • Reduce spam request from client (compare with Polling)
  • Good performance

Cons:

  • One way only
  • Limited browser support compared to HTTP

Websocket

Pros

  • Real-time absolutely
  • Fast connection, send and receive data
  • 2-way connection
  • Excellent performance (in two-way direction)

Cons

  • Costly for both server and client to keep connecting
  • High complexity

When to use

  • Polling using for small app and priority feature more than performance.

  • SSE suitable for medium app, building notification, live feed update, ...

  • Websocket suitable for chat app, streaming, gaming, collaboration app,...

Anti-pattern

  • Avoid using Websocket for small app, notification (SSE is more suitable)
  • Using combination of Polling and SSE for chatting, streaming, gaming instead of Websocket.
  • Using Websocket + SSE for chat and notification. This lead unnecessary (SSE) because Websocket can using for both Chat and Notification. (except you have specific cases that prefer SSE than Websocket - in most cases, Websocket can handle both).

Conclusion

  • Using Polling to reduce complexity of small app
  • Using SSE for notification, real-time feature (not the keys feature)
  • Using Websocket for chat, streaming