# Build Real-Time Collaborative Cursors: Figma-Style Presence

Source: https://www.techinterview.org/post/3233475141/build-real-time-collaborative-cursors/
Updated: 2026-05-05 · techinterview.org

Live cursors — those tiny avatars showing where other people are clicking — became table stakes for collaborative apps after Figma popularized them. The interview tests whether you understand the WebSocket plumbing, the throttling, the smooth-interpolation tricks, and the presence layer that powers them.

## Functional requirements

- Show other users' cursor positions in real time

- Each cursor has a name/avatar

- Cursors disappear when users leave

- Smooth movement, not jumpy

- Scales to dozens of concurrent users on the same document

## Architecture

WebSocket connection per client. Server broadcasts cursor positions to all clients on the same document.

For high-scale: each document is partitioned to a single server instance. WebSocket clients on that document connect to that instance directly, avoiding cross-instance routing.

## Throttling

Mouse moves fire many events per second — too many to broadcast.

Client-side throttling:

- Sample mouse position at 30Hz (every 33ms)

- Only send if position changed by >1 pixel

- Dispatch over WebSocket as a small binary message

Server-side throttling:

- Optional: aggregate cursor updates and broadcast batches every 50ms instead of one-by-one

- Reduces fanout cost at high concurrency

## Smooth interpolation

The receiving client gets cursor updates at ~30Hz. To render at 60fps without stutter, interpolate:

- Buffer the last 2 received positions

- Tween between them using requestAnimationFrame

- If new position arrives, smoothly transition to it

The result feels like 60fps movement even though server pushes at 30Hz.

## Cursor metadata

Each cursor needs:

- User ID (for color assignment)

- Name (initial display)

- Avatar (optional)

- Color (deterministic from user ID, so it is stable across sessions)

## Presence layer

Beyond cursors:

- Active users list (sidebar, top bar)

- "Who is editing this" tags on individual elements

- Selection rectangles (for shape tools, highlight a user's selection)

Presence is a separate channel from data updates. Don't conflate.

## Disappearing cursors

When a user disconnects:

- Server detects WebSocket close

- Broadcasts "user left" to others

- Other clients fade their cursor with a 200ms transition

Edge case: brief network drops. Use a "last seen" timeout (30 seconds) before declaring a user gone.

## Coordinate systems

The cursor position must translate between:

- The sender's viewport coordinates

- The document's logical coordinates

- The receiver's viewport (with their own pan/zoom)

Send logical coordinates over the wire. Each client transforms to their own viewport.

## Bandwidth

Per-user bandwidth: ~30 messages/sec × 50 bytes = 1.5 KB/sec downlink per user. With 50 users on a document, each client receives 75 KB/sec — fine on broadband.

For mobile or constrained network, reduce update rate to 15Hz or only send when significant change.

## Implementation libraries

- **Liveblocks:** drop-in presence + cursors + collaboration. Most-used in 2026.

- **Yjs / PartyKit:** CRDT-based; more flexible, more setup

- **Custom:** for full control, build on raw WebSocket

## Common mistakes

- Sending mouse events on every browser event (60+ Hz)

- Hard-coded colors that collide between users

- No interpolation — cursors jump from frame to frame

- Cursors persisting after users leave (zombie cursors)

- Coordinate system mismatch between sender and receiver

## Frequently Asked Questions

### How do you handle a tab going inactive?

Browser throttles requestAnimationFrame. Document.visibilityState event tells you the tab is hidden. Pause sending updates; clear cursor on remote clients.

### What is the latency budget?

Sub-100ms feels real-time. 200–300ms feels noticeable but acceptable. Above 500ms feels broken.

### Why does Figma feel smoother than competitors?

Significant engineering on the cursor pipeline: aggressive throttling, smart interpolation, partition-aware connection management. Other apps cut corners and feel jittery.
