Skip to main content

Command Palette

Search for a command to run...

Building a Real-Time Collaborative E-Learning Platform with WebSockets

Published
2 min read

Building a Real-Time Collaborative E-Learning Platform with WebSockets

E-learning is broken when the classroom isn't live. Here's how I built a platform where students and instructors collaborate in real time.

The problem

Polling sucks. Traditional HTTP requests waste bandwidth and battery. For a classroom with 40 students, polling every 500ms means 1,440 request/min per student—that's 57,600 requests hitting a single server every minute just to check if anything changed.

The solution: WebSockets + Redis

  1. Socket.io for persistent bidirectional connections

    • Auto-reconnection on network drop
    • Rooms for class isolation (each classroom is a room)
    • Fallback to long-polling for networks that block WebSockets
  2. Redis pub/sub to scale beyond a single server

    • Instructor broadcasts → Redis → all connected students
    • Scales horizontally (add servers, they all sub to same Redis channel)
    • Persistence for replay (store messages, let latecomers catch up)
  3. React hooks for synced UI state

    • useEffect listens to socket events and hydrates local state
    • Optimistic UI: student drags a whiteboard stroke → emits immediately, UI updates now (doesn't wait for server ack)
    • Conflict resolution: if two students draw at same pixel, last-write-wins (simpler than CRDT for a classroom)

Architecture

Instructor Browser
        ↓ (socket.emit('broadcast_slide_change'))
Socket.io Server (Node.js)
        ↓ (redis.publish('classroom:42', { slide: 3 }))
Redis Pub/Sub
        ↓ (distributes to all servers listening on 'classroom:42')
Socket.io Server Replicas
        ↓ (socket.emit('slide_changed', { slide: 3 }))
Student Browsers (40 tabs connected to any server)

The hard parts

Latency: Over cellular, round-trip to instructor's broadcast can be 500ms+. Students see the instructor move before the whiteboard updates. We solved this with predictive rendering — students draw locally first, server acks 50ms later, and if positions diverged, we tween back.

Dropped sockets: WiFi kicks students mid-class. On reconnect, they need to re-enter the room and catch up on the last 2 minutes of content. We store the last 100 events in Redis and replay them.

Cost: Every persistent connection is memory. At peak, we had 200 classrooms (8,000 students). Each socket takes ~2 KB of state. That's 16 MB just for socket metadata. Proper Redis tuning + connection pooling was essential.

Results

  • Latency: <100ms from instructor action to student's UI update (90th percentile)
  • Concurrent: 8,000 students across 20 classroom instances
  • Cost: $400/mo for Socket.io servers + $150/mo for Redis cluster

Polling this scale would have been 10x the server cost.


If you're building real-time features, the key insight is: persistent connections are cheaper than polling at scale. The upfront investment in WebSockets + Redis pays off immediately once you exceed 50 concurrent users.

See the full code and live demo at my portfolio.

More from this blog