From Setback to Success: Mastering Backend Web Development After Revoked Offers

Harianant SinhaHarianant Sinha
4 min read

🌱 Introduction

My job offer got revoked this spring💔. It stung, but instead of folding, I decided to double-down on learning web development.

Frontend was my comfort zone — backend? Total jungle. 🐒 I walked in and saw tech names flying everywhere: JWT, Express, MongoDB, WebSockets… it felt like I’d need a map just to survive.

Today, I took one step forward: learning WebSockets — a small but essential piece of the real-time app puzzle.


😅 Facing the Backend Beast

When I first peeked into backend development, it felt like walking into a library where all the books were written in different languages — Express, JWT, MongoDB, WebSockets… I didn’t even know where to start. My brain wanted to stick with the pretty buttons and colors of frontend. But I knew that if I wanted to build complete applications, I had to make peace with the backend. So I started small, tackling one technology at a time — no rush, just steady progress. Today’s battle? WebSockets. ⚔️


⚡ What is WebSocket?

WebSockets give you a persistent, full-duplex connection between browser and server — unlike HTTP’s request/response model.

Once connected, both sides can send messages anytime. Perfect for 💬 chats, 📊 live dashboards, and 🎮 multiplayer games.


🧩 How It Works (Quick)

  • Client-side: In the browser, you create a socket:

      const socket = new WebSocket('ws://localhost:8080');
    
  • Server-side: With Node.js + ws library, you listen for connections:

      const WebSocket = require('ws');
      const server = new WebSocket.Server({ port: 8080 });
    
    💡
    Messages are simply data exchanged between the client and server.

🚀 What I Built Today — 3 Levels of WebSocket Learning

1️⃣ Basic — Broadcast Messages to Everyone

Goal: Every incoming message to the server is broadcast to all connected clients.

// Broadcasting the message recieved to all the open clients
wss.on("connection", (ws) => {
    console.log("Client connected.");
    ws.on("message", (message) => {
        console.log("Received from one client: %s", message);
        console.log("Broadcasting message to all clients...");
        // Iterate over every client connected to the server
        wss.clients.forEach((client) => {
            // Check if the client is not the sender and is ready to receive messages
            if (client.readyState === ws.OPEN) {
                // Send the message to all clients 
                client.send(message.toString());
            }
        });
    });
});

✅ It worked immediately—my first "real-time client-server communication" moment! 🎉


2️⃣ Intermediate — Don’t Echo to Sender

Goal: Build a simple chat app that broadcasts a client's message to all other active clients, excluding the sender.

wss.on("connection", (ws) => {
    console.log("Client connected.");
    ws.on("message", (message) => {
        console.log("Received from one client: %s", message);
        console.log("Broadcasting message to all clients...");
        // Iterate over every client connected to the server
        wss.clients.forEach((client) => {
            // Check if the client is not the sender and is ready to receive messages
            if (client.readyState === WebSocket.OPEN && client!==ws) {
                // Send the message to THIS client in the loop
                client.send(`Message from sender: ${message.toString()}`);
            }
        });
    });
});

3️⃣ Advanced — Unique IDs & Disconnect Alerts

Goal: Create an intermediate Chat App where each client has a unique ID

// For this I shall use Uuid package for generating the user id:
const { v4: uuidv4 } = require('uuid');

Messages now look like:

Received message from client 02ad354e-8232-46f1-b546-020b1f923e97: Hello, this is message from client

When a client disconnects, the server broadcasts:

Client 02ad354e-8232-46f1-b546-020b1f923e97 disconnected

Putting it all together:

wss.on("connection",(ws)=>{
    ws.id = uuidv4();
    console.log(`Client connected with ID: ${ws.id}`);
    ws.on("message", (message) => {
        console.log(`Received message from client ${ws.id}:  ${message}`);
        console.log("Broadcasting message to all clients...");
        // Iterate over every client connected to the server
        wss.clients.forEach((client) => {
            // Check if the client is not the sender and is ready to receive messages
            if (client.readyState === WebSocket.OPEN && client!==ws) {
                // Send the message to THIS client in the loop
                client.send(`Message from sender ${ws.id}: ${message.toString()}`);
            }
        });
    });
    ws.on('close', () => {
        console.log(`Client ${ws.id} disconnected.`);
        // Broadcast the disconnect message to all remaining clients
        wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(`User ${ws.id} has left the chat.`);
            }
        });
    });
})

Suddenly it’s not just “data” — it feels like people coming and going. 🧑‍🤝‍🧑


💡 Wrap-Up / Takeaway

Big insight: Managing connections is as important as sending data. IDs, states, and disconnect handling turn sockets from pipes into conversations.

Backend was my biggest fear — too many tech names, too many moving parts — but breaking it into small levels made progress steady and fun.

Next stop: adding JWT authentication and storing messages in MongoDB so the chat history survives page reloads. 🚀

If you’ve had a setback or wrestled with backend concepts, let’s swap notes! 🤝


📓 PS – My Engineering Diary

Every day, I log exactly what I learn — topics, difficulties, breakthroughs — in a simple markdown file. I even have a tiny script that creates the daily template for me (one command, done ✅).

If you’re curious to see every step of this backend learning journey — not just the highlights — you can browse the full diary here:

📂 My Engineering Diary on GitHub

📬 Like this post? Subscribe so you don’t miss the next step in the journey — I’m posting every win, fail along the way.

0
Subscribe to my newsletter

Read articles from Harianant Sinha directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Harianant Sinha
Harianant Sinha

Hi, I'm Harianant Sinha. I'm a software engineer driven by a passion for building tangible solutions from the ground up. My experience is centered on two areas: crafting scalable, full-stack applications and diving deep into the world of Artificial Intelligence. This blog is where I document my journey, share what I'm learning in public, and explore the intersection of practical engineering and cutting-edge AI. My goal is to use technology to solve real-world problems, and I'm excited to share my process with you. Feel free to connect with me on LinkedIn or check out my code on GitHub.