MindForge
MindForge
DashboardHelp & Support
Dashboard
MindForge

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
WebSockets and Real-Time Systems
Course contents

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
Browsing without an account — progress is saved in this browser only.Sign in to save it

WebSockets and Real-Time Systems

Reading50 min

Chat, live notifications, collaborative editing, and trading dashboards all rest on one idea: a connection that stays open so either side can push a message whenever it wants. This lesson covers the WebSocket protocol itself, building an endpoint in FastAPI, managing connections at scale, what interviewers actually care about, which is what happens when a connection breaks, and how you scale real-time delivery past a single process.

The WebSocket protocol

HTTP is request-response: the client asks, the server answers, and the connection mostly closes. A WebSocket is a persistent, full-duplex connection where either side can push a message at any time, without the other side asking first. It starts life as a normal HTTP request and gets upgraded:

GET /ws/chat HTTP/1.1
Host: mindforge.test
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

The server answers 101 Switching Protocols, and from then on both sides speak the WebSocket framing protocol over that same TCP socket. There are no more HTTP headers per message, just lightweight frames, data frames plus control frames for ping, pong, and close. That's the whole reason a WebSocket is cheaper than polling: one handshake, one TCP connection, no repeated HTTP overhead on every single message.

WebSocket is not "HTTP but faster." It's a different protocol layered on top of the same initial handshake. It also isn't the only option:

Approach Direction Overhead Use when
Polling Client pulls High (repeated HTTP requests) Simple, infrequent updates
Long polling Client pulls, server holds the request open Medium No WebSocket support, near-real-time is good enough
Server-Sent Events (SSE) Server pushes to the client only Low One-way streams, like a feed or notifications
WebSocket Full duplex Low, after the handshake Chat, gaming, collaborative editing

Remember: a WebSocket starts as an HTTP request and upgrades once; everything after that is lightweight frames on the same TCP socket, not repeated HTTP requests.

Sign in to try this knowledge check.

A FastAPI WebSocket endpoint

Python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect

app = FastAPI()


@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
    await websocket.accept()
    try:
        while True:
            data = await websocket.receive_text()
            await websocket.send_text(f"echo: {data}")
    except WebSocketDisconnect:
        print(f"{client_id} disconnected")

await websocket.accept() completes the upgrade from HTTP to WebSocket. The while True loop is the connection's whole lifetime: it runs until the client disconnects, and a disconnect raises WebSocketDisconnect rather than the loop just returning normally.

Common mistake: forgetting the try/except around the loop. Every single disconnect then raises an unhandled exception, quietly spamming your logs and error tracker on completely normal client behavior.

Remember: a disconnect is a raised WebSocketDisconnect, not a quiet return. Always wrap the receive loop so a normal disconnect doesn't look like a crash.

Sign in to try this knowledge check.

Managing many connections

A single endpoint handling one socket isn't a system. You need a registry so you can broadcast, target a specific user, and clean up after a disconnect.

Python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from typing import Dict, Set

app = FastAPI()


class ConnectionManager:
    def __init__(self):
        # user_id -> set of active sockets (a user can have multiple tabs/devices)
        self.active_connections: Dict[str, Set[WebSocket]] = {}

    async def connect(self, user_id: str, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.setdefault(user_id, set()).add(websocket)

    def disconnect(self, user_id: str, websocket: WebSocket):
        connections = self.active_connections.get(user_id)
        if connections:
            connections.discard(websocket)
            if not connections:
                del self.active_connections[user_id]

    async def send_personal(self, user_id: str, message: str):
        for ws in self.active_connections.get(user_id, ()):
            await ws.send_text(message)

    async def broadcast(self, message: str, exclude_user: str | None = None):
        for user_id, sockets in self.active_connections.items():
            if user_id == exclude_user:
                continue
            for ws in sockets:
                await ws.send_text(message)


manager = ConnectionManager()


@app.websocket("/ws/{user_id}")
async def websocket_endpoint(websocket: WebSocket, user_id: str):
    await manager.connect(user_id, websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.broadcast(f"{user_id}: {data}", exclude_user=user_id)
    except WebSocketDisconnect:
        manager.disconnect(user_id, websocket)
        await manager.broadcast(f"{user_id} left the chat")

Notice disconnect always runs inside the except block. Cleanup on disconnect isn't optional: skip it, and dead socket references pile up quietly, each one erroring out the moment you try to send to it again, which is a slow memory leak in disguise.

Remember: always clean up a user's socket reference in the disconnect path. A registry that never forgets dead sockets is a leak waiting to be noticed in production.

Sign in to try this knowledge check.

Handling failure: heartbeats, reconnects, and backpressure

Networks drop. Mobile clients switch from Wi-Fi to cellular mid-conversation. An interviewer wants to hear you plan for this, not assume a happy path.

  • Ping/pong heartbeats. WebSocket has built-in ping/pong control frames. Without them, a half-dead TCP connection, the client vanished with no proper close, can sit in your server's connection pool for a long time before the OS notices. Send a ping periodically; if no pong comes back within a timeout, treat the connection as dead and clean it up.
Python
import asyncio

async def heartbeat(websocket: WebSocket, interval: int = 30, timeout: int = 10):
    while True:
        await asyncio.sleep(interval)
        try:
            await asyncio.wait_for(websocket.send_text('{"type":"ping"}'), timeout=timeout)
        except (asyncio.TimeoutError, Exception):
            await websocket.close()
            break
  • Client-side reconnect with exponential backoff. The client should treat a disconnect as normal, not exceptional, and reconnect automatically, backing off (1s, 2s, 4s, 8s, capped) so it doesn't hammer a server that's already struggling.
  • No delivery guarantee by default. A WebSocket gives you no "at least once" promise on its own. If the socket drops mid-send, that message is simply gone. For anything that must not be lost, chat history, order events, persist the message server-side before pushing it, and let the client ask for "everything since sequence N" on reconnect so it can catch up.
  • Backpressure. A slow client on a bad connection can't drain messages as fast as the server produces them. Calling send_text without limits lets those messages pile up in memory. Use a bounded queue per connection, and drop or disconnect a client that falls too far behind rather than let server memory grow without limit.

Remember: a WebSocket guarantees delivery to no one by default. Persist anything that can't be lost before you push it, so a client can catch up after reconnecting.

Sign in to try this knowledge check.

Scaling WebSockets past one process

This is the question that separates "I built a demo" from "I understand production systems."

The core problem: WebSocket connections are stateful and sticky. A client is connected to exactly one server process, unlike stateless HTTP, where any server in a pool can handle any request. A ConnectionManager like the one above only knows about sockets on its own process. If user A is connected to server 1 and user B to server 2, server 1's in-memory broadcast never reaches user B.

The fix is a shared pub/sub backbone, Redis Pub/Sub, or Kafka for higher durability, that every server instance subscribes to. When a server needs to deliver a message to a user who might be connected to a different instance, it publishes to the shared channel; every instance receives it and forwards it to any locally connected sockets for that user.

Python
import redis.asyncio as redis
import json

class ScalableConnectionManager:
    def __init__(self, redis_url: str):
        self.local_connections: Dict[str, Set[WebSocket]] = {}
        self.redis = redis.from_url(redis_url)
        self.pubsub = self.redis.pubsub()

    async def start(self):
        await self.pubsub.subscribe("broadcast")
        asyncio.create_task(self._listen())

    async def _listen(self):
        async for message in self.pubsub.listen():
            if message["type"] != "message":
                continue
            payload = json.loads(message["data"])
            for ws in self.local_connections.get(payload["user_id"], ()):
                await ws.send_text(payload["text"])

    async def publish(self, user_id: str, text: str):
        # Any server instance can call this; only the instance holding
        # that user's live socket will actually deliver it.
        await self.redis.publish("broadcast", json.dumps({"user_id": user_id, "text": text}))

Two more pieces worth naming even if you don't code them in an interview: connection count is the bottleneck, not CPU. A single process can hold tens of thousands of idle WebSocket connections, since each one is cheap, a socket plus a small buffer, so scaling is about connection count and message fan-out volume, not raw compute. And presence and session state belong in Redis, not in-process memory, so any instance can answer "is user X online" and route accordingly. Sticky sessions at the load balancer still help a reconnect land back on a familiar instance, but the pub/sub layer above removes the hard requirement for it.

Remember: a WebSocket connection is sticky to one process. A shared Redis Pub/Sub (or Kafka) channel is what lets any server instance deliver a message to a user connected to a different one.

Sign in to try this knowledge check.

Putting it together: a minimal chat server

Python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from collections import defaultdict
import json

app = FastAPI()
rooms: dict[str, set[WebSocket]] = defaultdict(set)


@app.websocket("/ws/{room_id}/{username}")
async def chat_endpoint(websocket: WebSocket, room_id: str, username: str):
    await websocket.accept()
    rooms[room_id].add(websocket)
    await _broadcast(room_id, {"type": "join", "user": username})

    try:
        while True:
            raw = await websocket.receive_text()
            await _broadcast(room_id, {"type": "message", "user": username, "text": raw})
    except WebSocketDisconnect:
        rooms[room_id].discard(websocket)
        await _broadcast(room_id, {"type": "leave", "user": username})


async def _broadcast(room_id: str, payload: dict):
    dead = []
    for ws in rooms[room_id]:
        try:
            await ws.send_text(json.dumps(payload))
        except Exception:
            dead.append(ws)  # client vanished mid-send
    for ws in dead:
        rooms[room_id].discard(ws)

This single-process version is what you'd realistically write in a 45-minute interview. Say out loud that production needs the Redis pub/sub layer above it to fan out across multiple server instances. That one sentence shows you know exactly where the demo stops and the real system begins.

Remember: a working single-process chat server plus one sentence about the Redis fan-out layer needed in production is the complete interview answer. You don't need to code the scaled version live.

Sign in to try this knowledge check.
PreviousAPI Security and AuthenticationNextDocker and Containers

Course progress

0%
0 of 177 modules complete

On this page

  • The WebSocket protocol
  • A FastAPI WebSocket endpoint
  • Managing many connections
  • Handling failure: heartbeats, reconnects, and backpressure
  • Scaling WebSockets past one process
  • Putting it together: a minimal chat server