- Lab
-
Libraries: If you want this lab, consider one of these libraries.
- Core Tech
Guided: Real-time Communication with Web Sockets
Welcome to the code lab: Guided: Real-time Communication with WebSockets. This lab is an essential resource for developers who want to build applications that deliver instant, live-updating user experiences through WebSocket-based communication. How do you enable real-time messaging between clients? How does a WebSocket connection work behind the scenes? And how can you broadcast updates to multiple users instantly? This Code Lab is designed to help you answer these questions through practical, hands-on learning. By the end of this Code Lab, you will have the skills to establish a WebSocket connection, exchange live messages between the client and server, and broadcast events to all connected users. This will empower you to build scalable, responsive, and interactive web applications that feel alive.
Lab Info
Table of Contents
-
Challenge
Introduction and Setup
Real Time Communication
Real-time communication means the UI updates as soon as new data exists, not when the user refreshes or clicks.
Most traditional web apps work like this:
- Browser requests data from server (HTTP)
- Server responds
- The connection closes
- If the browser wants updates, it must request again
That model is great for pages and one-off requests, but it breaks down for:
- Chat messages
- Live dashboards (sales activity, monitoring metrics)
- Presence (“who’s online”)
- Notifications
- Collaborative editing
Because those use cases require the server to “push” updates.
WebSockets vs Polling vs REST
REST = client-driven communication
- Client asks: “Give me the latest messages”
- Server answers with messages (or none)
Polling = REST repeated on a timer
- Client asks every 2 seconds: “Any new messages?”
- Often gets “no updates”, which wastes bandwidth and server CPU
Long polling = slightly better polling
- Client requests “any new messages”
- Server holds the request open until a message exists
- When it responds, the client immediately asks again
- This reduces wasted “no updates”, but it’s still an HTTP trick.
WebSockets = persistent, two-way channel
- One connection stays open
- Client can send messages anytime
- Server can send messages anytime
- No need to constantly open/close connections
Why WebSockets are better for chat
Chat is: frequent messages, small payloads, bursty patterns (quiet… then lots of messages) and requires low latency
WebSockets fit perfectly because they avoid repeated setup cost. ### Explore the starter project structure
Open the project folder
websocket-chat-lab.Think of this as two systems that will talk as you will find in the
srcfolder, two folders:- Client: displays messages, sends messages, shows connection state
- Server: acts like a relay/switchboard, ensuring messages reach all clients
Important: WebSockets do not automatically broadcast.
A WebSocket server receives messages from one client, but it won’t share them with others unless you implement that logic.
Try and start the server to see the baseline page by running the following commands in the terminal:
cd websocket-chat npm startWhen it says that it is listening to port 3001, go to the Web Browser tab or navigate to {{localhost:3001}} to see the html chat page (you may need to refresh the browser tab).
Important: After each step where you edit the server or the client, make sure to stop and restart the server by rerunning
npm startin the terminal. Also refresh the browser page so you can see the changes take effect.info > If you get stuck on a task, there are solution files for each task you can refer to in the
solutionsfolder. -
Challenge
Creating the WebSocket Server
WebSockets begin with an HTTP request called an “Upgrade” request.
Browser says:
- “I want to upgrade this HTTP connection to a WebSocket protocol”
Server says:
- “Yes, switching protocols” Then the connection becomes persistent and stays open.
We attach WebSockets to the same HTTP server because:
- Same host/port makes development simpler
- Avoids CORS headaches
- Mirrors how production often works (reverse proxy -> app) What happens when you initialize this command
new WebSocket("ws://localhost:3001")?
The server:
- Receives a handshake
- Verifies it
- Emits a "connection" event
- Gives you a ws object representing that specific client
That ws object is like a private wire to that client. ### Test connection from browser console
After completing the previous task, it’s easy to test the connection from the browser’s DevTools console. The following code is an example of how to set up a WebSocket connection by creating a new WebSocket instance and subscribing to its events, such as
onopen,onmessage,onclose, andonerror:const ws = new WebSocket("wss://example.com"); ws.onopen = () => console.log("Connected!"); ws.onmessage = (e) => console.log("Server says:", e.data); ws.onclose = () => console.log("Closed"); ws.onerror = (e) => console.log("Error", e);This code is the core WebSocket logic in
server.jsthat you will continue enhancing throughout the rest of the lab. -
Challenge
Implementing Client-Side Messaging
A WebSocket has states:
- CONNECTING (0)
- OPEN (1)
- CLOSING (2)
- CLOSED (3)
If you try to send while not OPEN, the message fails.
That’s why real apps always:
- Track connection status
- Disable the “send” button while disconnected
- Handle reconnect ### Serialize messages with JSON
In real systems, messages aren’t just “text”. They have meaning:
- Chat message
- System notification
- User joined
- User left
- Typing indicator
- Error
So you can send structured messages like:
{ "type": "chat", "from": "Eman", "message": "Hello!" }This allows:
- Consistent processing
- Future feature expansion
- Easier debugging
-
Challenge
Broadcasting Messages to All Clients
Broadcasting Messages to All Clients
wss.clientsis a Set of all currently connected sockets. Each represents one browser tab or one user session.Broadcasting means:
- Loop through every client
- Check they are still open
- Send the message payload
Important nuance:
- Some sockets can be half-closed or broken
- So check readyState === OPEN ### Multi-tab test
A WebSocket app might work in one tab but fail as a chat system.
Multi-tab testing proves:
- Broadcasting works
- Server handles multiple connections simultaneously
- State isn’t tied to one client
-
Challenge
Handling Connection Lifecycle & Debugging
Handling Lifecycle & Debugging
In WebSockets, presence is a core feature. Even if you aren’t building user lists, join/leave events:
- Help users understand what’s happening
- Help debugging (“did my connection drop?”)
- Are vital for collaborative systems
Server detects join/leave through:
- "connection" event (join)
- "close" event (leave) ### Connection status UI: why UX matters in real-time apps
Without status, users will think:
- The message didn’t send
- The system is broken
- They are being ignored
Real-time apps should always show:
- Connecting
- Connected
- Disconnected
- Reconnecting
And disable message input if offline. ### Auto-reconnect strategy
When connection drops, naive apps reconnect instantly in a tight loop:
- That can overwhelm your own server
- It increases traffic during outages
- It causes “reconnect storms” if many clients do it at once
So you can use a gradual delay known as "Exponential Backoff": 1s, 2s, 3s, up to a cap. This is a simple form of backoff.
-
Challenge
Conclusion and Best Practices
Security: why WebSockets need special attention
WebSockets are long-lived connections. That means:
- One authenticated session stays open longer
- If you don’t validate inputs, attackers can keep sending data
- Messages can be spammed quickly
Must-haves in production:
- WSS (TLS)
- Authentication (cookies/token)
- Schema validation
- Message size limits
- Rate limiting ### Scaling: why broadcasting breaks with multiple servers
If you run 2 server instances:
- Client A connects to server 1
- Client B connects to server 2
Broadcast on server 1 won’t reach server 2’s clients.
Solutions:
- Sticky sessions + shared pub/sub
- Redis Pub/Sub fanout
- Managed real-time infrastructure WebSocket issues often feel random without metrics.
Track:
- Number of active connections
- Disconnect reasons
- Messages/sec
- Memory usage
- Latency (send → receive time)
About the author
Real skill practice before real-world application
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Learn by doing
Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.
Follow your guide
All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.
Turn time into mastery
On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.