π Building an HTTP Server from Scratch in Node.js (No Express)

Today, I took a deep dive into how backend servers actually work under the hood by building a simple HTTP server using Node.js β without using Express.(By the help of Chatgpt).
Harkirat Singh youtube channel full stack developer roadmap video helps me to get in this basic understanding.
This helped me understand what really happens behind the scenes when we send requests and receive responses.
ποΈ Step 0: Setting Up the Project (What I Did First)
Before writing any code, I initialized my project using:
npm init -y
This step creates a proper Node.js environment.
π¦ What did this create?
1. package.json
This is the core file of any Node.js project.
Example:
{ "name": "http-server", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" } }
Why itβs important:
Stores project details (name, version)
Keeps track of dependencies
Allows running commands like: npm start
Think of it as the identity + configuration of your project.
2. package-lock.json
This file is automatically created to lock exact versions of dependencies.
Why this matters:
Ensures your project works the same on every system
Prevents version mismatch issues
Simple idea:
package.json β what you want
package-lock.json β what you actually installed
3. node_modules/ (created later)
When you install packages:
npm install express
This folder stores all installed libraries.
Important Note:
For a basic HTTP server, npm init is not strictly required.
But:
Real-world projects always use it
Keeps everything organized
Makes your project scalable
π§ Step 1: Creating a Server
Node.js provides a built-in http module to create servers:
const http = require('http');
const server = http.createServer((req, res) => { res.end("Hello World"); });
server.listen(3000, () => { console.log("Server running on port 3000"); });
req β Incoming request
res β Response sent back
π Understanding Request & Response Flow
When a client sends a request:
Request comes into the server (req)
Server processes it
Server sends response (res.end())
π‘ Handling Routes Manually
Unlike Express, we manually check routes:
if (req.method === 'GET' && req.url === '/') { res.end("Server is running"); }
π¦ Handling POST Requests (Important)
POST data doesnβt come at once β it comes in chunks.
let body = '';
req.on('data', chunk => { body += chunk.toString(); });
req.on('end', () => { const parsed = JSON.parse(body); console.log(parsed); });
Key Concepts:
data β receives chunks
end β all data received
JSON.parse() β string β object
π JSON Handling
JSON.parse() β string β object
JSON.stringify() β object β string
HTTP transfers data as strings, so conversion is required.
π§ Array Operations
Used .find() to check if a user exists:
const user = USERS.find(u => u.email === email);
Returns object if found
Returns undefined if not
βοΈ Destructuring
Extracting values from objects:
const { email, password } = parsed;
Makes code cleaner and readable.
π₯ Adding Data
USERS.push({ email, password });
Adds new user data.
π€ Sending Proper Response
res.setHeader('Content-Type', 'application/json'); res.statusCode = 200; res.end(JSON.stringify({ message: "Success" }));
π§ͺ Testing with curl
curl -X POST http://localhost:3000/signup -H "Content-Type: application/json" -d '{"email":"test@gmail.com","password":"123"}'
Breakdown:
-X POST β request method
-H β headers
-d β data (payload)
π‘ Key Learnings
Node.js uses streams for handling data
Requests come in chunks
APIs are just route handlers
JSON is the standard data format
Project setup (npm init) is essential for real-world development
π Final Thought
Building a server without Express gave me a clear understanding of how things work internally. Now frameworks like Express feel much easier and more meaningful.
Thanks for reading π

