View : 217

08/05/2026 06:51am

EP.120 Whiteboard & Real-time Drawing Synchronization with WebSocket

EP.120 Whiteboard & Real-time Drawing Synchronization with WebSocket

#Golang The Series

#WebSocket

#Golang

#Go

#whiteboard

After building a collaborative document editor using text sync, itโ€™s time to move toward something even more challenging real-time drawing.

 

Apps like Miro, FigJam, and Excalidraw must support highly interactive features such as:

  • Multiple users drawing at the same time

  • Real-time shape, stroke, and cursor movement

  • Shared canvas state that stays perfectly in sync

  • Instant Undo/Redo

  • Ultra-low latency

 

In this article, you'll learn how to build a real-time Whiteboard System using Go + WebSocket, with architecture and code thatโ€™s ready for production use.

 

๐Ÿง  System Architecture Overview

 
Client (Canvas)
  โ†• WebSocket
Whiteboard Server (Go)
  โ†• Broadcast
All clients in the same board

 

Key Components

  • Canvas State โ€“ Current state of the board

  • Draw Events โ€“ Stroke or shape actions

  • Cursor Position โ€“ Each user's real-time pointer

  • History Stack โ€“ For Undo/Redo functionality

  • Room (Board) โ€“ Scoped by board_id for isolated sessions

 

โœ๏ธ 1. Drawing Event Data Format

 

Rather than syncing the whole canvas, we only send draw events:

{
  "board_id": "board-001",
  "user_id": "user-a",
  "type": "draw",
  "tool": "pen",
  "points": [
    { "x": 120, "y": 240 },
    { "x": 122, "y": 245 }
  ],
  "color": "#FF0000",
  "stroke": 2 } 

 

Supported event types include:

  • draw (pen, brush)

  • shape (rectangle, circle, arrow)

  • cursor

  • undo, redo

  • clear

 

โš™๏ธ 2. Server-side Data Structures (Go)

 
type DrawEvent struct {
	BoardID string      `json:"board_id"`
	UserID  string      `json:"user_id"`
	Type    string      `json:"type"`
	Tool    string      `json:"tool"`
	Points  []Point     `json:"points,omitempty"`
	Color   string      `json:"color,omitempty"`
	Stroke  int         `json:"stroke,omitempty"`
}

type Point struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

 

Each whiteboard session is managed via board_id to broadcast only within its own room.

 

๐Ÿ”„ 3. Real-time WebSocket Sync

 
var boards = make(map[string]map[*websocket.Conn]bool)

func handleWhiteboard(conn *websocket.Conn, boardID string) {
	if boards[boardID] == nil {
		boards[boardID] = make(map[*websocket.Conn]bool)
	}
	boards[boardID][conn] = true

	defer func() {
		delete(boards[boardID], conn)
		conn.Close()
	}()

	for {
		var event DrawEvent
		if err := conn.ReadJSON(&event); err != nil {
			return
		}
		broadcast(boardID, event)
	}
}

func broadcast(boardID string, event DrawEvent) {
	for c := range boards[boardID] {
		c.WriteJSON(event)
	}
}

 

Result: User A draws something โ†’ all users see it instantly

Latency: Millisecond-level performance

 

๐Ÿ–ฑ๏ธ 4. Real-time Mouse / Cursor Sync

 

To show what others are doing on the canvas:

{
  "type": "cursor",
  "user_id": "user-b",
  "x": 450,
  "y": 300 } 

 

  • Clients send cursor position every ~50ms

  • Server broadcasts to all clients in the same room

 

โ†ฉ๏ธ 5. Real-time Undo / Redo

 

Concept:

  • Each draw event = one action

  • Maintain a history stack per board

 
type BoardHistory struct {
	Undo []DrawEvent
	Redo []DrawEvent
}

 

Undo:

  • Pop from undo, push to redo

  • Broadcast to all clients to remove the last action

 

โšก 6. Performance Optimization

 

Important when scaling to many users:

  • Send only deltas, not entire strokes

  • Throttle cursor updates (30โ€“60 fps)

  • Batch frequent events

  • Use binary protocol for large boards

  • Split canvas into layers: background / drawing / cursor

 

๐Ÿ” 7. Security & Access Control

 

Your system should include:

  • Board permissions (read / write access)

  • Rate limits per user

  • Shape validation to avoid malformed payloads

  • Protection against spam/flooding

 

๐Ÿš€ Mini Project Challenge

 

Try building a real demo that supports:

  • 2โ€“3 users drawing in real-time

  • Cursor sync

  • Instant Undo/Redo

  • Open multiple tabs they must stay 100% synced

 

โœ… If you can build all this, youโ€™ve truly mastered real-time drawing synchronization ๐ŸŽฏ

 


 

๐Ÿ”ฎ Coming Next: EP.121 Deploying WebSocket Server on Kubernetes

 

In the next episode, weโ€™ll go full production.

Youโ€™ll learn how to:

  • Deploy your WebSocket Server with Kubernetes

  • Set up Load Balancer with Sticky Sessions

  • Implement Auto-Scaling to support thousands of connections

Stay tuned! ๐Ÿš€