Introduction: The Reception Desk of AQAD
Imagine AQAD has grown into a large B2B marketplace.
Every day:
- Vendors upload products
- Retailers place orders
- Logistic partners update deliveries
- Employees monitor operations
Now imagine there is no reception desk.
Customers arrive.
Nobody receives them.
Nobody understands their requests.
Nobody provides responses.
Chaos.
A backend server works very much like a reception desk.
It receives requests.
Processes them.
Returns responses.
This communication happens through something called:
HTTP
Before Node.js can become a real backend application, it must be able to:
- Accept requests
- Process requests
- Send responses
This chapter teaches exactly how that happens.
By the end of this chapter, you will understand how APIs and backend systems actually begin.
What Is HTTP?
HTTP stands for:
HyperText Transfer Protocol
Don't worry about memorizing the full form.
Think of HTTP as a language.
A language used by:
Browser
↔
Server
to communicate.
Real-Life Analogy
Imagine a customer enters a restaurant.
Customer:
Can I have a coffee?
Waiter:
Sure.
Kitchen prepares coffee.
Waiter returns:
Here is your coffee.
The conversation contains:
Request
Customer asking for something.
Response
Restaurant providing something.
HTTP works exactly the same way.
Understanding Client and Server
Every HTTP communication involves two parties.
Client
Requests information.
Examples:
- Browser
- Mobile App
- React Application
- React Native Application
Server
Provides information.
Examples:
- Node.js Backend
- Express API
- AQAD Backend
Example:
Retailer App
↓
Request Products
↓
AQAD Backend
↓
Return Products
What Happens When You Open a Website?
Suppose you visit:
https://aqad.com
Browser sends:
HTTP Request
Server processes it.
Server returns:
HTTP Response
Browser displays result.
This happens in milliseconds.
Creating Your First HTTP Server
Node.js includes a built-in module:
http
Import it:
const http = require('http');
No installation required.
Creating the Server
Example:
const http = require('http');
const server = http.createServer();
server.listen(3000);
Server now listens on:
http://localhost:3000
But it doesn't do anything yet.
Understanding createServer()
Think of:
http.createServer()
as opening the reception desk.
The desk exists.
But nobody is handling customers yet.
Handling Requests
Let's improve our server.
const http = require('http');
const server =
http.createServer(
(req, res) => {
res.end(
'Welcome to AQAD'
);
}
);
server.listen(3000);
Visit:
http://localhost:3000
Output:
Welcome to AQAD
Congratulations.
You built your first backend server.
Understanding req and res
Inside:
(req, res)
Node.js provides two objects.
req
Request Object.
Contains information sent by client.
res
Response Object.
Used to send information back.
Think of:
reqas: Customer Request
and
resas: Restaurant Response
Understanding listen()
Example:
server.listen(3000);
Meaning:
Server
Listen on Port 3000
What Is a Port?
Think of a building.
One building.
Many doors.
Door 3000
Door 5000
Door 8080
Ports help computers identify services.
Common ports:
| Port | Purpose |
|---|---|
| 80 | HTTP |
| 443 | HTTPS |
| 3000 | Development |
| 5000 | APIs |
| 3306 | MySQL |
Adding a Startup Message
Useful for development.
server.listen(3000,() => {
console.log( 'Server Running');
}
);
Output:
Server Running
Accessing Request Information
Suppose user visits:
http://localhost:3000
Print request URL.
const server =
http.createServer(
(req, res) => {
console.log(
req.url
);
res.end('Hello');
}
);
Output:
/
Visit:
http://localhost:3000/products
Output:
/products
Interesting.
Now the server knows what page was requested.
Understanding Routing
Routing means:
Different URL
↓
Different Response
Example:
const server = http.createServer((req, res) => {
if(req.url === '/'){
res.end('Home Page');
}
}
);
Visit:
/
Output:
Home Page
Multiple Routes
Example:
const server = http.createServer((req, res) => {
if(req.url === '/'){
res.end('Home'); }
else if(req.url === '/products'){
res.end('Products');
}else{
res.end('Page Not Found' ); }
});
Visit:
/products
Output:
Products
AQAD Example
Imagine:
/products
/orders
/vendors
Each route returns different information.
Example:
if(req.url === '/products'){
res.end('Product List');
}
Understanding HTTP Methods
URL alone is not enough.
Clients also send methods.
Common methods:
| Method | Purpose |
|---|---|
| GET | Fetch data |
| POST | Create data |
| PUT | Update data |
| DELETE | Remove data |
GET Request
Retrieve information.
Example:
GET /products
Meaning:
Give me products.
POST Request
Create information.
Example:
POST /products
Meaning:
Create product.
Checking Request Method
Example:
console.log(req.method);
Output:
GET
AQAD Example
Retailer:
GET /products
Fetch products.
Vendor:
POST /products
Create product.
Returning HTML
Response can contain HTML.
Example:
res.end(`<h1>AQAD Marketplace</h1>`);
Browser displays:
AQAD Marketplace
as heading.
Returning JSON
Modern APIs mostly return JSON.
Example:
const products = [
{
id: 1,
name: 'Rice'
}
];
res.end(
JSON.stringify(products)
);
Output:
[
{
"id":1,
"name":"Rice"
}
]
Why JSON Is Important
Frontend applications understand JSON easily.
Examples:
- React
- React Native
- Angular
- Vue
All communicate using JSON.
Setting Response Headers
Headers provide metadata.
Example:
res.setHeader(
'Content-Type',
'application/json'
);
Then:
res.end(
JSON.stringify(data)
);
Browser now understands:
JSON Response
Understanding Status Codes
Every response includes a status.
Examples:
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 404 | Not Found |
| 500 | Server Error |
Example
res.statusCode = 200;
res.end(
'Success'
);
Not Found Example
res.statusCode = 404;
res.end('Page Not Found');
Output:
404
AQAD API Example
if(req.url === '/products'){
res.statusCode = 200;
res.end('Products Found');
}
Unknown route:
res.statusCode = 404;
res.end('Not Found');
Building a Mini AQAD API
Example:
const http = require('http');
const server = http.createServer((req,res)=>{
if(req.url === '/products'){
const products = [
{
id:1,
name:'Rice'},
{
id:2,
name:'Milk'}
];
res.setHeader('Content-Type','application/json');
res.end(JSON.stringify(products));
}else{
res.statusCode = 404;
res.end('Route Not Found'); }
});
server.listen(3000);
Visit:
http://localhost:3000/products
Output:
[
{
"id":1,
"name":"Rice"
},
{
"id":2,
"name":"Milk"
}
]
Common Beginner Mistakes
Mistake 1
Forgetting res.end()
Bad:
res.write('Hello');
Without: res.end();
request never finishes.
Mistake 2
Ignoring Status Codes
Always return meaningful status codes.
Mistake 3
Sending Objects Directly
Bad:
res.end(products);
Good:
res.end(JSON.stringify(products));
Mistake 4
Not Setting Content-Type
JSON responses should use:
application/json
Mini Exercises
Exercise 1
Create:
/
route.
Return:
Welcome
Exercise 2
Create:
/products
route.
Return JSON.
Exercise 3
Print:
req.url
for every request.
Exercise 4
Return:
404 Not Found
for unknown routes.
Try It Yourself
Create:
const http =
require('http');
const server = http.createServer((req,res)=>{
res.statusCode = 200;
res.end('Hello AQAD');
});
server.listen(3000,()=>{
console.log('Server Running');
});
Run:
node app.js
Visit:
http://localhost:3000
Observe your first real backend response.
Interview Question
What is the difference between req and res in Node.js?
Good Answer:
The req object contains information sent by the client such as URL, method, and headers. The res object is used by the server to send responses back to the client including data, headers, and status codes.
Real Developer Insight
When beginners first create:
http.createServer()
it may look simple.
But behind this small function lies the foundation of:
- REST APIs
- Express.js
- Authentication systems
- Payment gateways
- E-commerce platforms
- Social media applications
Everything starts with understanding how a server receives requests and sends responses.
Once you understand HTTP servers, frameworks like Express become much easier because they are built on top of the same concepts.
Node.js Interview Questions and Real-World Scenarios
Introduction: Why Interview Preparation Matters
Imagine two developers applying for the same Node.js Backend Developer position.
Both have learned:
- JavaScript
- Node.js
- APIs
- Databases
Both can write code.
Both understand the basics.
But during the interview:
Developer A memorizes definitions.
Developer B explains:
- Why Node.js was created
- How the Event Loop works
- Why Streams improve performance
- How a production backend handles thousands of users
Which developer gets hired?
Usually Developer B.
Because companies don't hire developers who simply memorize answers.
They hire developers who understand how systems work.
The goal of this chapter is not to help you memorize interview answers.
The goal is to help you think like a backend developer.
We'll cover:
- Beginner questions
- Intermediate questions
- Advanced scenarios
- Real production examples
- AQAD marketplace case studies
Beginner-Level Questions
Question 1: What Is Node.js?
Answer:
Node.js is a JavaScript runtime environment built on Google's V8 Engine.
It allows JavaScript to run outside the browser and enables developers to build backend applications, APIs, command-line tools, and real-time systems.
Interview Tip
Don't say:
"Node.js is a programming language."
That is incorrect.
JavaScript is the language.
Node.js is the runtime.
Question 2: Why Was Node.js Created?
Answer:
Before Node.js, JavaScript mainly ran inside browsers.
Ryan Dahl created Node.js to allow JavaScript to run on servers and handle many concurrent connections efficiently using an event-driven, non-blocking architecture.
Question 3: What Is the V8 Engine?
Answer:
V8 is Google's JavaScript engine.
It converts JavaScript code into machine code so the computer can execute it quickly.
Node.js uses V8 to run JavaScript outside the browser.
Question 4: What Is NPM?
Answer:
NPM stands for Node Package Manager.
It helps developers install, manage, and share reusable packages.
It includes:
- Package registry
- Package manager
- CLI tool
Question 5: What Is package.json?
Answer:
package.json is the configuration file of a Node.js project.
It contains:
- Project information
- Dependencies
- Scripts
- Version details
- Metadata
Intermediate-Level Questions
Question 6: What Is the Event Loop?
Answer:
The Event Loop is the mechanism that allows Node.js to handle asynchronous operations without creating a new thread for every request.
It continuously checks:
Call Stack
Callback Queue
Microtask Queue
and decides what should execute next.
Restaurant Analogy
Think of the Event Loop as a head waiter.
The waiter doesn't cook food.
The waiter coordinates activities and ensures tasks happen at the right time.
Question 7: What Is Non-Blocking I/O?
Answer:
Non-blocking I/O allows Node.js to start an operation and continue doing other work instead of waiting for the operation to finish.
Example:
fs.readFile(
'data.txt',
callback
);
Node.js continues executing other code while the file is being read.
Question 8: What Is libuv?
Answer:
libuv is a C library used by Node.js.
It provides:
- Event Loop implementation
- Thread Pool
- Non-blocking I/O operations
libuv helps Node.js perform tasks such as:
- File operations
- DNS lookups
- Networking
Question 9: Difference Between require() and import?
require()
CommonJS
const fs =
require('fs');
import
ES Modules
import fs
from 'fs';
Modern projects increasingly use:
import
export
Question 10: What Are Environment Variables?
Answer:
Environment variables store configuration values outside the codebase.
Examples:
PORT
JWT_SECRET
DATABASE_URL
AWS_REGION
They improve:
- Security
- Flexibility
- Deployment management
Event Loop Interview Questions
These questions appear frequently.
Question 11: Predict the Output
console.log('A');
setTimeout(() => {
console.log('B');
}, 0);
console.log('C');
Output:
A
C
B
Why?
The timeout callback enters the callback queue.
Node.js executes synchronous code first.
Question 12: Predict the Output
console.log('Start');
Promise.resolve()
.then(() => {
console.log('Promise');
});
console.log('End');
Output:
Start
End
Promise
Why?
Promises use:
Microtask Queue
which executes after synchronous code finishes.
Streams Interview Question
Question 13: Why Use Streams?
Answer:
Streams process data in chunks instead of loading entire files into memory.
Benefits:
- Lower memory consumption
- Better performance
- Improved scalability
Example
Bad:
fs.readFile()
for huge files.
Better:
fs.createReadStream()
Buffers Interview Question
Question 14: What Is a Buffer?
Answer:
A Buffer is a temporary memory area used to store raw binary data.
It is commonly used for:
- Files
- Streams
- Images
- Network communication
Modules Interview Question
Question 15: What Is Module Caching?
Answer:
When a module is loaded using:
require()
Node.js stores it in memory.
Future requests use the cached version instead of reading the file again.
Benefits:
- Faster execution
- Better performance
Advanced Interview Questions
Question 16: Why Is Node.js Single-Threaded?
Answer:
Node.js uses a single-threaded event loop to simplify concurrency and reduce resource consumption.
However, Node.js is not limited to one thread.
libuv internally uses:
Thread Pool
for tasks like:
- File operations
- DNS lookups
- Cryptography
Question 17: Can Node.js Handle Thousands of Users?
Answer:
Yes.
Because Node.js uses:
- Event-driven architecture
- Non-blocking I/O
- Efficient resource utilization
it can handle many concurrent connections.
Example
Netflix and other large-scale companies have used Node.js for high-traffic systems.
Question 18: Difference Between process.nextTick() and setTimeout()
process.nextTick()
Runs before the next Event Loop phase.
setTimeout()
Runs during the Timers phase.
Example:
process.nextTick(() => {
console.log('Tick');
});
setTimeout(() => {
console.log('Timeout');
}, 0);
Output:
Tick
Timeout
Real Production Scenarios
These questions test practical thinking.
Scenario 1
AQAD API Suddenly Becomes Slow
Symptoms:
High Response Time
Users Complaining
CPU Usage Increased
What Would You Check?
Answer:
- CPU usage
- Memory usage
- Database performance
- Slow queries
- Application logs
- Network latency
Tools:
- CloudWatch
- PM2
- Grafana
- Node.js logs
Scenario 2
Memory Usage Keeps Increasing
Symptoms:
Application Starts Fine
Memory Grows Constantly
Eventually Crashes
Likely Cause:
Memory Leak
What To Investigate?
- Global variables
- Unclosed connections
- Cached data
- Event listeners
Scenario 3
Large CSV Upload Crashes Server
Vendor uploads:
5 GB CSV
Server crashes.
Bad Solution:
fs.readFile()
Better Solution:
fs.createReadStream()
Use streams.
AQAD Marketplace Case Study
Let's combine everything.
Requirement
Retailer places order.
System must:
Save Order
Update Inventory
Notify Vendor
Send Email
Generate Analytics
Beginner Solution
saveOrder();
updateInventory();
sendEmail();
notifyVendor();
analytics();
Everything tightly coupled.
Better Solution
orderEmitter.emit(
'orderCreated'
);
Listeners:
Inventory Service
Notification Service
Analytics Service
Email Service
More scalable.
System Design Style Question
How Would You Design Product Upload API?
Answer:
Step 1
Authentication
JWT verification.
Step 2
Validate request.
Step 3
Upload images.
Step 4
Store files.
S3 or file storage.
Step 5
Save product metadata.
Database.
Step 6
Emit event.
productCreated
Step 7
Update analytics.
Frequently Asked Node.js Interview Mistakes
Mistake 1
Saying:
Node.js is a programming language.
Wrong.
Mistake 2
Thinking:
setTimeout(fn, 0)
runs immediately.
Wrong.
Mistake 3
Not understanding Event Loop.
Very common interview failure.
Mistake 4
Confusing Node.js with Express.js.
Express is a framework.
Node.js is the runtime.
Mistake 5
Ignoring real-world architecture questions.
Senior interviews focus on:
- Scalability
- Reliability
- Monitoring
- Security
not just syntax.
Mini Interview Challenge
Explain in your own words:
Question 1
Why is Node.js suitable for APIs?
Question 2
Why are streams useful?
Question 3
What happens when:
node app.js
is executed?
Question 4
How does Event Loop improve scalability?
Real Developer Advice
Many developers spend weeks memorizing interview answers.
Unfortunately:
Interviewers can easily detect memorization.
Instead:
Focus on understanding:
- Why Node.js exists
- How requests flow
- How Event Loop works
- How data moves through streams
- How backend systems scale
When you understand the concepts, answers become natural.
Real Backend Project Structure – How Professional Node.js Applications Are Organized
Introduction: Why Professional Projects Don't Have Everything Inside app.js
When developers first learn Node.js, their projects usually look like this:
project
│
└── app.js
Inside:
// Login Logic
// Product Logic
// Orders Logic
// Payment Logic
// Email Logic
// Database Logic
// Validation Logic
// File Upload Logic
At first this feels manageable.
Then the project grows.
After a few weeks:
app.js
=
2,000 Lines
A few months later:
app.js
=
10,000 Lines
Now imagine AQAD running like this.
One employee handles:
- Vendor onboarding
- Retailer onboarding
- Orders
- Inventory
- Payments
- Logistics
- Analytics
Impossible.
Businesses grow by creating departments.
Software grows exactly the same way.
Professional backend applications divide responsibilities into folders and modules.
This chapter shows how real Node.js applications are structured in production environments.
The Goal of Project Structure
A good backend structure helps:
Scalability
Add new features easily.
Maintainability
Fix bugs faster.
Team Collaboration
Multiple developers work simultaneously.
Code Reusability
Avoid duplicate logic.
Clean Architecture
Easy to understand.
AQAD Backend Structure
A professional Node.js project might look like:
aqad-backend
│
├── src
│
├── config
│
├── routes
│
├── controllers
│
├── services
│
├── middlewares
│
├── models
│
├── validations
│
├── utils
│
├── uploads
│
├── logs
│
├── app.js
│
└── server.js
Don't worry.
We'll understand every folder.
Understanding Request Flow
Before discussing folders, let's understand what happens when a request arrives.
Example:
Retailer
↓
GET /products
↓
Route
↓
Middleware
↓
Controller
↓
Service
↓
Database
↓
Response
This flow exists in most professional backend systems.
Routes Folder
Think of routes as reception desks.
Real-Life Analogy
A customer enters AQAD headquarters.
Reception asks:
Which department do you need?
Routes perform the same job.
Example:
routes
│
├── userRoutes.js
├── productRoutes.js
├── orderRoutes.js
└── paymentRoutes.js
Example:
router.get(
'/products',
getProducts
);
The route simply decides:
This request belongs to Product Controller
Nothing more.
Controllers Folder
Controllers handle incoming requests.
Restaurant Analogy
Customer says:
I want a coffee.
Waiter receives the request.
The waiter doesn't prepare the coffee.
The waiter forwards the request.
Controllers work similarly.
Example:
controllers
│
├── userController.js
├── productController.js
└── orderController.js
Example:
const getProducts =
async (req, res) => {
const products =
await productService
.getProducts();
res.json(products);
};
Controller responsibilities:
- Receive request
- Validate input
- Call service
- Send response
Why Controllers Should Stay Small
Bad:
const getProducts =
async (req,res)=>{
// 500 lines
// Database
// Validation
// Business Logic
}
Good:
const getProducts =
async (req,res)=>{
const products =
await productService
.getProducts();
res.json(products);
}
Controllers should remain lightweight.
Services Folder
Services contain business logic.
This is where the real work happens.
AQAD Example
When retailer places order:
Business rules may include:
Check Inventory
Calculate Total
Apply Discounts
Calculate Tax
Generate Invoice
Create Order
These belong inside services.
Example:
services
│
├── productService.js
├── orderService.js
└── paymentService.js
Example:
const createOrder =
async (data) => {
// Inventory Check
// Pricing Logic
// Order Creation
};
Why Services Matter
Without services:
Controllers become massive.
With services:
Controller
↓
Service
↓
Database
Clean separation.
Models Folder
Models represent database structures.
AQAD Example
Tables:
Users
Products
Orders
Payments
Each table gets a model.
Example:
models
│
├── userModel.js
├── productModel.js
└── orderModel.js
Model responsibility:
Interact with database.
Example:
const getProductById =
async (id) => {
return productTable
.find(id);
};
Validation Folder
Validation protects applications from bad data.
Example
Vendor creates product.
Bad request:
{
"price": -100
}
Should not be accepted.
Validation checks:
Required Fields
Email Format
Phone Format
Password Rules
Price Rules
Folder:
validations
│
├── userValidation.js
├── productValidation.js
└── orderValidation.js
Example:
const schema = {
title: required,
price: positive
};
Middleware Folder
Middleware sits between:
Request
↓
Controller
Think of middleware as security guards.
Authentication Middleware
Example:
User Request
↓
JWT Verification
↓
Allow Access
Example:
const authMiddleware =
(req,res,next)=>{
// Verify Token
next();
}
Logging Middleware
Every request gets recorded.
Example:
GET /products
POST /orders
PUT /users
Useful for monitoring.
Rate Limiting Middleware
Protects APIs.
Example:
100 Requests
Per Minute
Prevent abuse.
Config Folder
Stores application configuration.
Example:
config
│
├── database.js
├── aws.js
└── environment.js
Instead of:
const region =
'me-central-1';
hardcoded everywhere.
Use:
config.aws.region
Environment Variables
Never store secrets inside code.
Bad:
const secret =
'my-secret-key';
Good:
process.env.JWT_SECRET
Example:
PORT=5000
JWT_SECRET=secret
AWS_REGION=me-central-1
Utils Folder
Utilities contain reusable helper functions.
Example:
utils
│
├── dateHelper.js
├── fileHelper.js
└── generateId.js
Example:
generateOrderId()
used throughout project.
Uploads Folder
Stores uploaded files.
AQAD Example:
uploads
│
├── products
│
├── vendors
│
└── retailer-documents
Contains:
- Images
- PDFs
- Trade licenses
- Documents
Logs Folder
Stores application logs.
Example:
logs
│
├── errors.log
├── orders.log
└── system.log
Useful for troubleshooting.
app.js vs server.js
Many professional projects separate them.
app.js
Contains:
Routes
Middlewares
Configurations
Example:
const app =
express();
app.use(...);
server.js
Starts server.
Example:
app.listen(
5000
);
This separation improves testing.
Real AQAD Request Flow
Retailer requests:
GET /products
Flow:
Route
↓
Auth Middleware
↓
Controller
↓
Service
↓
Database
↓
Response
Let's see this visually.
Route
router.get(
'/products',
getProducts
);
Controller
const getProducts =
async(req,res)=>{
const data =
await productService
.getProducts();
res.json(data);
}
Service
const getProducts =
async()=>{
return productModel
.getAll();
}
Model
const getAll =
async()=>{
return db.products;
}
Response:
[
{
"id":1,
"title":"Rice"
}
]
Each layer has one responsibility.
Why This Architecture Scales
Imagine AQAD grows from:
1,000 Retailers
to:
100,000 Retailers
New features become easier because:
- Routes stay organized
- Controllers stay clean
- Services contain logic
- Models manage data
The project remains maintainable.
Common Beginner Mistakes
Mistake 1
Putting Everything Inside Controller
Bad:
// Validation
// Database
// Business Logic
// Response
inside controller.
Mistake 2
Skipping Services
Many beginners directly call database from controller.
This becomes difficult to maintain.
Mistake 3
Hardcoding Secrets
Bad:
const jwtSecret =
'123456';
Always use environment variables.
Mistake 4
Creating Huge Utility Files
Bad:
utils.js
containing:
300 Functions
Split logically.
Mistake 5
Ignoring Logging
Production systems need logs.
Mini Exercise
Design folder structure for:
Library Management System
Create:
routes
controllers
services
models
middlewares
and decide responsibilities.
Try It Yourself
Create:
project
│
├── routes
├── controllers
├── services
├── models
│
├── app.js
└── server.js
Build:
GET /products
flow using all layers.
This exercise helps understand architecture much better than memorizing theory.
Real Developer Insight
Junior developers often think:
"A good developer writes code."
Senior developers know:
"A good developer organizes code."
Most production issues are not caused by lack of coding ability.
They are caused by poor architecture.
A clean architecture allows:
- Faster development
- Easier debugging
- Better teamwork
- Easier scaling
This is why companies care so much about project structure.

0 Comments