Course contentsShow
← Node.js
Lesson 1132 of 1,98010. Real-time Communication and WebsocketsFree lesson

Building a Collaborative Cursor Tracking System

You will implement high-frequency coordinate broadcasting while managing bandwidth costs.

In this lesson, you will learn how to build a collaborative cursor tracking system by balancing real-time responsiveness with server-side bandwidth constraints.

When multiple users track their mouse movements on a shared canvas, sending every single pixel coordinate would overwhelm your WebSocket server. A typical mouse can trigger over 100 events per second; if you have 50 active users, that’s 5,000 messages per second, leading to severe network bottlenecks.

The Throttling Strategy

To manage this, we employ event throttling. Instead of emitting a packet on every mousemove event, we use a controlled interval or a request-animation-frame loop to "sample" the cursor position.

On the client side, we store the current coordinates in a local variable and only broadcast them to the server if a specific time threshold has passed (e.g., every 30ms).

// Client-side: Throttled broadcast
let lastCursorPos = { x: 0, y: 0 };
let lastEmitTime = 0;

window.addEventListener('mousemove', (e) => {
  lastCursorPos = { x: e.clientX, y: e.clientY };
  
  const now = Date.now();
  if (now - lastEmitTime > 30) { // Limit to ~33 broadcasts per second
    socket.emit('cursor-move', lastCursorPos);
    lastEmitTime = now;
  }
});

Server-Side Efficiency

On the backend, you shouldn't broadcast every incoming coordinate to every connected client individually. If you have 100 users, broadcasting each update to everyone creates an O(N2)O(N^2) traffic complexity. Instead, use a broadcast buffer. Every 50ms, the server collects all pending cursor updates and sends them as a single "batch" array to all clients. This reduces the number of WebSocket frames significantly while maintaining a smooth visual experience for your users.

To further save bandwidth, represent cursor positions as simple integer arrays [x, y] instead of verbose JSON objects like {"x": 100, "y": 200}. Over thousands of updates, stripping those extra characters adds up to substantial savings in your monthly egress costs.

Key Takeaway: Never stream raw mouse events directly; always throttle client-side broadcasts and batch server-side payloads to maintain scalability without sacrificing visual fluidity.