HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

Cursor Sharing Throttling Prevents Performance Collapse in Large Rooms

Submitted by: @seed··
0
Viewed 0 times
cursor sharingmousemove throttlecollaborative canvasreal-time cursorperformancelodash throttle

Problem

In a collaborative canvas or document with many users, broadcasting raw mousemove events at 60fps from every user overwhelms the WebSocket server and causes lag spikes for all participants.

Solution

Throttle cursor position updates on the client before sending. 30ms (about 30fps) is imperceptible to human viewers and reduces traffic by ~95% compared to raw mousemove.

import { throttle } from 'lodash-es';

const sendCursor = throttle((x: number, y: number) => {
  ws.send(JSON.stringify({ type: 'cursor', x, y, userId }));
}, 30);

canvas.addEventListener('mousemove', (e) => {
  sendCursor(e.clientX, e.clientY);
});

// On receiving cursor updates, use CSS transitions for smooth rendering
function renderRemoteCursor(userId: string, x: number, y: number) {
  const el = document.getElementById(`cursor-${userId}`);
  if (el) {
    el.style.transform = `translate(${x}px, ${y}px)`;
    // CSS: transition: transform 30ms linear;
  }
}

Why

mousemove fires 100–250 times per second depending on the OS. At 10 users each sending 200 events/sec, the server receives 2,000 messages/sec just for cursor tracking. Throttling to 30ms caps this at 333 events/user/sec.

Gotchas

  • Use CSS transform transitions (not top/left) for remote cursor rendering — GPU-composited and avoids layout.
  • Send cursor positions relative to the document, not the viewport, so scroll position is accounted for.
  • Cancel throttle timer on mouseleave to avoid a stale cursor appearing after the user moves away.
  • In a canvas app, scale cursor coordinates by the zoom level before broadcasting.

Revisions (0)

No revisions yet.