Lesson 28 of 49 advanced

WebSockets & Real-Time

Live Updates Without Refreshing

Open interactive version (quiz + challenge)

Real-world analogy

Normal HTTP is like sending letters — you send a question, wait for a reply. WebSockets are like a phone call — once connected, both sides can talk anytime! That's how live chat, notifications, and collaborative editing work.

What is it?

WebSockets provide a persistent, bidirectional communication channel between client and server. Unlike HTTP (request-response), WebSocket connections stay open, allowing the server to push data to clients in real-time.

Real-world relevance

Slack, Discord, WhatsApp Web, Google Docs collaborative editing, live sports scores, stock tickers — all use WebSockets for real-time updates.

Key points

Code example

// 1. NestJS WebSocket Gateway 🚀
@WebSocketGateway({
  cors: { origin: '*' },
})
export class ChatGateway {
  @WebSocketServer()
  server: Server;

  // When a client sends a message
  @SubscribeMessage('sendMessage')
  handleMessage(client: Socket, payload: { room: string; text: string }) {
    // Broadcast to everyone in the room
    this.server.to(payload.room).emit('newMessage', {
      text: payload.text,
      sender: client.id,
      timestamp: new Date(),
    });
  }

  // When a client joins a room
  @SubscribeMessage('joinRoom')
  handleJoinRoom(client: Socket, room: string) {
    client.join(room);
    this.server.to(room).emit('userJoined', {
      message: `Someone joined the room!`,
    });
  }
}

// 2. React client — connect and listen 📡
import { io } from 'socket.io-client';

const socket = io('http://localhost:3000');

function ChatRoom({ room }: { room: string }) {
  const [messages, setMessages] = useState<any[]>([]);

  useEffect(() => {
    socket.emit('joinRoom', room);

    socket.on('newMessage', (msg) => {
      setMessages(prev => [...prev, msg]);
    });

    return () => { socket.off('newMessage'); };
  }, [room]);

  const sendMessage = (text: string) => {
    socket.emit('sendMessage', { room, text });
  };

  return (
    <div>
      {messages.map((msg, i) => (
        <div key={i}>{msg.text}</div>
      ))}
      <input placeholder="Type..." onKeyDown={(e) => {
        if (e.key === 'Enter') sendMessage(e.currentTarget.value);
      }} />
    </div>
  );
}

Line-by-line walkthrough

  1. 1. 1. NestJS WebSocket Gateway 🚀
  2. 2. Decorator that adds metadata or behavior
  3. 3.
  4. 4.
  5. 5. Exporting for use in other files
  6. 6. Decorator that adds metadata or behavior
  7. 7.
  8. 8.
  9. 9. When a client sends a message
  10. 10. Decorator that adds metadata or behavior
  11. 11.
  12. 12. Broadcast to everyone in the room
  13. 13.
  14. 14.
  15. 15.
  16. 16.
  17. 17.
  18. 18. Closing block
  19. 19.
  20. 20. When a client joins a room
  21. 21. Decorator that adds metadata or behavior
  22. 22.
  23. 23.
  24. 24.
  25. 25.
  26. 26.
  27. 27. Closing block
  28. 28. Closing block
  29. 29.
  30. 30. 2. React client — connect and listen 📡
  31. 31. Importing required dependencies
  32. 32.
  33. 33. Declaring a variable
  34. 34.
  35. 35. Declaring a function
  36. 36. Declaring a variable
  37. 37.
  38. 38.
  39. 39.
  40. 40.
  41. 41.
  42. 42.
  43. 43.
  44. 44.
  45. 45. Returning a value
  46. 46.
  47. 47.
  48. 48. Declaring a variable
  49. 49.
  50. 50. Closing block
  51. 51.
  52. 52. Returning a value
  53. 53.
  54. 54.
  55. 55.
  56. 56.
  57. 57.
  58. 58. Conditional check
  59. 59.
  60. 60.
  61. 61. Closing expression
  62. 62. Closing block

Spot the bug

@SubscribeMessage('sendMessage')
handleMessage(client: Socket, payload: { room: string; text: string }) {
  client.emit('newMessage', { text: payload.text });
}
Need a hint?
Who receives the message when you emit on client?
Show answer
client.emit() sends only to the sender, not everyone in the room. Fix: use this.server.to(payload.room).emit('newMessage', ...) to broadcast to the room.

Explain like I'm 5

Regular websites are like sending letters - you send a question, wait for an answer. WebSockets are like a phone call - once connected, both people can talk anytime! That's how live chat works - messages show up right away without refreshing.

Fun fact

Discord handles over 4 million WebSocket connections simultaneously on a single server using Elixir. That's like 4 million people on a phone call at the same time on one phone line! 📞

Hands-on challenge

Build a collaborative 'cursor tracker' — when a user moves their mouse on the page, broadcast their cursor position and username to all other connected users. Display colored dots for each user's cursor in real-time. Add a 'user is typing...' indicator that disappears after 2 seconds of inactivity. How would you handle 50+ users without flooding the network?

More resources

Open interactive version (quiz + challenge) ← Back to course: Full-Stack Playbook