← work

08 - Case Study

PM Tool

Real-time Kanban with WebSockets - Monday.com from scratch

PM Tool
Timeline2021
RoleFull-Stack Engineer
StackReact, Node.js, Express.js, MongoDB, Socket.io
StatusIn development

The Problem

Real-time collaboration is one of those features that sounds straightforward until you try to implement it. Drag-and-drop task reordering across multiple connected clients - where everyone sees the same board state instantly - involves synchronisation challenges most tutorials skip entirely.

What I Built

Socket.io for real-time board updates: every drag-and-drop action emits to a room, the server validates the new order, updates MongoDB, and broadcasts the confirmed state to all connected clients. Conflicts resolve server-side - last write wins with client-side optimistic updates.

01 - Real-Time Architecture

Socket.io rooms per project - users join a room when they open a board and leave when they navigate away. Task updates emit to the room, not to individual users. The server is the source of truth; clients optimistically update and roll back if the server rejects.

02 - Drag and Drop

The tricky part was reconciling the optimistic client-side order with the persisted MongoDB order during concurrent drags. Solved with a position field on each task and a debounced persist - the client shows the new order immediately, the server confirms within 300ms.

03 - Data Model

MongoDB schema with workspaces → projects → task lists → tasks. Flexible enough to support Kanban and List views without separate collections. Task assignments and comment threads are embedded documents - reduces join complexity at the cost of document size.

What Happened

01

Real-time board sync working across multiple simultaneous connected clients

02

Drag-and-drop with instant optimistic updates and server-confirmed persistence

03

WebSocket room management handles users moving between projects without stale listeners

In the Wild

In Hindsight

Embedded comments in task documents works until a task has hundreds of comments and every read pulls the full history. A separate comments collection with a task reference would have been cleaner at scale.