Node.js Real-World Practice Questions with Solutions

Introduction

Real-world Node.js development is more than writing small programs. Developers use Node.js to build APIs, backend services, authentication systems, file-processing applications, dashboards, and business applications. In this chapter, you will practice practical Node.js problems that are similar to tasks developers face in real projects. Each question starts simply and gradually introduces validation, APIs, files, databases, security, and project organization. Node.js Real-World practice questions with solutions help to understand the concepts.

Question 1: How do you create a simple user registration API?

Problem

Create a Node.js and Express.js API that accepts a user’s name, email, and age.

The API should:

  • Accept JSON data
  • Check required fields
  • Return the created user
  • Return an error when required data is missing

Solution

Install Express:

npm init -y
npm install express

Create app.js:

const express = require("express");

const app = express();

app.use(express.json());

app.post("/api/users", (req, res) => {

    const {
        name,
        email,
        age
    } = req.body;

    if (!name || !email || age === undefined) {

        return res.status(400).json({
            success: false,
            message: "Name, email and age are required."
        });

    }

    const user = {
        name: name,
        email: email,
        age: Number(age)
    };

    res.status(201).json({
        success: true,
        message: "User registered successfully.",
        user: user
    });

});

app.listen(3000, () => {

    console.log(
        "Server running on port 3000"
    );

});

Test Request

POST http://localhost:3000/api/users

JSON body:

{
    "name": "Rahul",
    "email": "rahul@example.com",
    "age": 20
}

Response

{
    "success": true,
    "message": "User registered successfully.",
    "user": {
        "name": "Rahul",
        "email": "rahul@example.com",
        "age": 20
    }
}

Step-by-Step Explanation

Read data from:

req.body

Validate it:

if (!name || !email || age === undefined) {
    ...
}

Create a user object:

const user = {
    name: name,
    email: email,
    age: Number(age)
};

Return HTTP status 201 because a new resource was created.


Question 2: How do you prevent duplicate email registration?

Problem

Create a registration API that does not allow two users to register with the same email address.

Solution

For this beginner-friendly example, store users in an array.

const express =
    require("express");

const app =
    express();

app.use(
    express.json()
);


const users = [];


app.post(
    "/api/register",
    (req, res) => {

        const {
            name,
            email
        } = req.body;

        if (!name || !email) {

            return res.status(400).json({

                success: false,

                message:
                    "Name and email are required."

            });

        }

        const existingUser =
            users.find(
                user =>
                    user.email.toLowerCase() ===
                    email.toLowerCase()
            );

        if (existingUser) {

            return res.status(409).json({

                success: false,

                message:
                    "Email is already registered."

            });

        }

        const user = {

            id:
                users.length + 1,

            name:
                name,

            email:
                email.toLowerCase()

        };

        users.push(
            user
        );

        res.status(201).json({

            success: true,

            message:
                "Registration successful.",

            user:
                user

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test First Request

{
    "name": "Rahul",
    "email": "rahul@example.com"
}

The user is created.

Send the Same Email Again

{
    "name": "Amit",
    "email": "rahul@example.com"
}

Response:

{
    "success": false,
    "message": "Email is already registered."
}

Step-by-Step Explanation

Search for an existing user:

const existingUser =
    users.find(
        user =>
            user.email.toLowerCase() ===
            email.toLowerCase()
    );

If found:

return res.status(409).json({
    ...
});

Question 3: How do you create a Todo API?

Problem

Build a simple Todo API that allows users to:

  • Create a todo
  • View all todos
  • Mark a todo as completed

Solution

const express =
    require("express");

const app =
    express();

app.use(
    express.json()
);


const todos = [];


app.post(
    "/api/todos",
    (req, res) => {

        const {
            task
        } = req.body;

        if (!task) {

            return res.status(400).json({

                success: false,

                message:
                    "Task is required."

            });

        }

        const todo = {

            id:
                todos.length + 1,

            task:
                task,

            completed:
                false

        };

        todos.push(
            todo
        );

        res.status(201).json({

            success: true,

            todo:
                todo

        });

    }
);


app.get(
    "/api/todos",
    (req, res) => {

        res.json({

            success: true,

            todos:
                todos

        });

    }
);


app.patch(
    "/api/todos/:id",
    (req, res) => {

        const id =
            Number(req.params.id);

        const todo =
            todos.find(
                item =>
                    item.id === id
            );

        if (!todo) {

            return res.status(404).json({

                success: false,

                message:
                    "Todo not found."

            });

        }

        todo.completed =
            true;

        res.json({

            success: true,

            message:
                "Todo completed.",

            todo:
                todo

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Create a Todo

POST /api/todos

JSON:

{
    "task": "Learn Node.js"
}

Response

{
    "success": true,
    "todo": {
        "id": 1,
        "task": "Learn Node.js",
        "completed": false
    }
}

Mark It Complete

PATCH /api/todos/1

Response

{
    "success": true,
    "message": "Todo completed.",
    "todo": {
        "id": 1,
        "task": "Learn Node.js",
        "completed": true
    }
}

Important Point

Todo applications are excellent beginner projects because they teach CRUD operations, API routes, request bodies, route parameters, and state changes.


Question 4: How do you create a file upload API?

Problem

Create a Node.js API that accepts an uploaded image.

Solution

Install Multer:

npm install express multer

Create app.js:

const express =
    require("express");

const multer =
    require("multer");

const path =
    require("path");

const app =
    express();


const storage =
    multer.diskStorage({

        destination:
            "uploads/",

        filename:
            (req, file, cb) => {

                const extension =
                    path.extname(
                        file.originalname
                    );

                const filename =
                    Date.now() +
                    extension;

                cb(
                    null,
                    filename
                );

            }

    });


const upload =
    multer({
        storage: storage
    });


app.post(
    "/api/upload",
    upload.single("image"),
    (req, res) => {

        if (!req.file) {

            return res.status(400).json({

                success: false,

                message:
                    "Image is required."

            });

        }

        res.json({

            success: true,

            message:
                "File uploaded successfully.",

            filename:
                req.file.filename

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Step-by-Step Explanation

Multer handles multipart form-data uploads.

The important middleware is:

upload.single("image")

It expects one uploaded file with the field name:

image

The uploaded file is available through:

req.file

Important Point

For production applications, validate file type, file size, filename handling, storage location, and access permissions before accepting uploads.


Question 5: How do you create a protected admin route?

Problem

Create an API where only requests containing a specific API key can access the admin route.

Solution

const express =
    require("express");

const app =
    express();


const API_KEY =
    "my-secret-key";


function checkApiKey(
    req,
    res,
    next
) {

    const key =
        req.headers["x-api-key"];

    if (key !== API_KEY) {

        return res.status(401).json({

            success: false,

            message:
                "Unauthorized access."

        });

    }

    next();

}


app.get(
    "/api/admin",
    checkApiKey,
    (req, res) => {

        res.json({

            success: true,

            message:
                "Welcome to the admin area."

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test Without API Key

GET /api/admin

Response:

{
    "success": false,
    "message": "Unauthorized access."
}

Test With API Key

Add this request header:

x-api-key: my-secret-key

The API will allow access.

Step-by-Step Explanation

Read the header:

req.headers["x-api-key"]

Check it:

if (key !== API_KEY) {
    ...
}

Allow the request:

next();

Important Point

This example teaches the middleware concept. Do not hard-code real secrets in source code. Production applications should use environment variables and a proper authentication system.


Question 6: How do you create an API that reads a JSON file?

Problem

Create a Node.js API that reads product information from a local JSON file.

Create products.json

[
    {
        "id": 1,
        "name": "Laptop",
        "price": 55000
    },
    {
        "id": 2,
        "name": "Keyboard",
        "price": 1500
    },
    {
        "id": 3,
        "name": "Mouse",
        "price": 800
    }
]

Create app.js

const express =
    require("express");

const fs =
    require("fs/promises");

const app =
    express();


app.get(
    "/api/products",
    async (req, res) => {

        try {

            const data =
                await fs.readFile(
                    "products.json",
                    "utf8"
                );

            const products =
                JSON.parse(data);

            res.json({

                success: true,

                products:
                    products

            });

        } catch (error) {

            console.error(
                error
            );

            res.status(500).json({

                success: false,

                message:
                    "Unable to read products."

            });

        }

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test

GET http://localhost:3000/api/products

Step-by-Step Explanation

Read the file:

await fs.readFile(
    "products.json",
    "utf8"
);

Convert JSON text into JavaScript data:

JSON.parse(data);

Return the data:

res.json({
    products: products
});

Important Point

A JSON file can be useful for small demonstrations, prototypes, and configuration-style data, but it is generally not a replacement for a database in a multi-user production application.


Question 7: How do you add search and pagination to a Node.js API?

Problem

Create an API that supports:

/api/products?search=laptop&page=1&limit=2

The API should search products and return only the requested page.

Solution

const express =
    require("express");

const app =
    express();


const products = [

    {
        id: 1,
        name: "Laptop",
        price: 55000
    },

    {
        id: 2,
        name: "Keyboard",
        price: 1500
    },

    {
        id: 3,
        name: "Mouse",
        price: 800
    },

    {
        id: 4,
        name: "Laptop Bag",
        price: 2000
    },

    {
        id: 5,
        name: "Monitor",
        price: 12000
    }

];


app.get(
    "/api/products",
    (req, res) => {

        const search =
            req.query.search || "";

        const page =
            Number(req.query.page) || 1;

        const limit =
            Number(req.query.limit) || 2;


        const filteredProducts =
            products.filter(
                product =>
                    product.name
                        .toLowerCase()
                        .includes(
                            search.toLowerCase()
                        )
            );


        const start =
            (page - 1) * limit;

        const end =
            start + limit;


        const results =
            filteredProducts.slice(
                start,
                end
            );


        res.json({

            success: true,

            page:
                page,

            limit:
                limit,

            total:
                filteredProducts.length,

            products:
                results

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test

GET http://localhost:3000/api/products?search=laptop&page=1&limit=2

Example Response

{
    "success": true,
    "page": 1,
    "limit": 2,
    "total": 2,
    "products": [
        {
            "id": 1,
            "name": "Laptop",
            "price": 55000
        },
        {
            "id": 4,
            "name": "Laptop Bag",
            "price": 2000
        }
    ]
}

Step-by-Step Explanation

Read query parameters:

req.query.search
req.query.page
req.query.limit

Calculate the starting position:

const start =
    (page - 1) * limit;

Get only the required records:

filteredProducts.slice(
    start,
    end
);

Important Point

Pagination becomes very important when an API contains thousands or millions of records. Production APIs should usually implement pagination at the database-query level rather than loading the entire dataset into memory.


Question 8: How do you create a centralized error handler?

Problem

Create an Express.js application where errors are handled by one central middleware instead of repeating error-response code everywhere.

Solution

const express =
    require("express");

const app =
    express();

app.use(
    express.json()
);


app.get(
    "/api/profile",
    (req, res, next) => {

        const error =
            new Error(
                "Profile could not be loaded."
            );

        next(error);

    }
);


app.use(
    (
        error,
        req,
        res,
        next
    ) => {

        console.error(
            error
        );

        res.status(500).json({

            success: false,

            message:
                "Something went wrong."

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test

GET http://localhost:3000/api/profile

Response

{
    "success": false,
    "message": "Something went wrong."
}

Step-by-Step Explanation

Create an error:

const error =
    new Error(
        "Profile could not be loaded."
    );

Pass it to the error middleware:

next(error);

The error handler has four parameters:

(
    error,
    req,
    res,
    next
)

Question 9: How do you create a health-check API for a real Node.js application?

Problem

Create an endpoint that tells you whether the Node.js application is running.

This type of endpoint is commonly useful for monitoring and deployment environments.

Solution

const express =
    require("express");

const app =
    express();


app.get(
    "/health",
    (req, res) => {

        res.status(200).json({

            status:
                "ok",

            message:
                "Application is running.",

            uptime:
                process.uptime(),

            timestamp:
                new Date().toISOString()

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Server running on port 3000"
        );

    }
);

Test

GET http://localhost:3000/health

Example Response

{
    "status": "ok",
    "message": "Application is running.",
    "uptime": 24.532,
    "timestamp": "2026-08-29T10:30:00.000Z"
}

Step-by-Step Explanation

process.uptime() tells you approximately how many seconds the Node.js process has been running.

process.uptime()

The timestamp is generated using:

new Date().toISOString()

Important Point

A health-check endpoint is useful for monitoring application availability. In a production system, a deeper readiness check may also verify dependencies such as the database.


Question 10: How do you build a small real-world backend project?

Problem

Build a Course Management API that allows an institute to manage courses.

The API should support:

GET     /api/courses
GET     /api/courses/:id
POST    /api/courses
PUT     /api/courses/:id
DELETE  /api/courses/:id

Solution

Step 1: Install Express

npm init -y
npm install express

Step 2: Create app.js

const express =
    require("express");

const app =
    express();

app.use(
    express.json()
);


let courses = [

    {
        id: 1,
        name: "Python Programming",
        duration: "3 Months",
        fee: 15000
    },

    {
        id: 2,
        name: "Web Development",
        duration: "6 Months",
        fee: 25000
    }

];


app.get(
    "/api/courses",
    (req, res) => {

        res.json({

            success: true,

            count:
                courses.length,

            courses:
                courses

        });

    }
);


app.get(
    "/api/courses/:id",
    (req, res) => {

        const id =
            Number(req.params.id);

        const course =
            courses.find(
                item =>
                    item.id === id
            );

        if (!course) {

            return res.status(404).json({

                success: false,

                message:
                    "Course not found."

            });

        }

        res.json({

            success: true,

            course:
                course

        });

    }
);


app.post(
    "/api/courses",
    (req, res) => {

        const {
            name,
            duration,
            fee
        } = req.body;

        if (
            !name ||
            !duration ||
            fee === undefined
        ) {

            return res.status(400).json({

                success: false,

                message:
                    "Name, duration and fee are required."

            });

        }

        const newCourse = {

            id:
                courses.length > 0
                    ? courses[courses.length - 1].id + 1
                    : 1,

            name:
                name.trim(),

            duration:
                duration.trim(),

            fee:
                Number(fee)

        };

        if (
            Number.isNaN(
                newCourse.fee
            )
        ) {

            return res.status(400).json({

                success: false,

                message:
                    "Fee must be a number."

            });

        }

        courses.push(
            newCourse
        );

        res.status(201).json({

            success: true,

            message:
                "Course created successfully.",

            course:
                newCourse

        });

    }
);


app.put(
    "/api/courses/:id",
    (req, res) => {

        const id =
            Number(req.params.id);

        const course =
            courses.find(
                item =>
                    item.id === id
            );

        if (!course) {

            return res.status(404).json({

                success: false,

                message:
                    "Course not found."

            });

        }

        const {
            name,
            duration,
            fee
        } = req.body;

        if (
            !name ||
            !duration ||
            fee === undefined
        ) {

            return res.status(400).json({

                success: false,

                message:
                    "Name, duration and fee are required."

            });

        }

        const numericFee =
            Number(fee);

        if (
            Number.isNaN(
                numericFee
            )
        ) {

            return res.status(400).json({

                success: false,

                message:
                    "Fee must be a number."

            });

        }

        course.name =
            name.trim();

        course.duration =
            duration.trim();

        course.fee =
            numericFee;

        res.json({

            success: true,

            message:
                "Course updated successfully.",

            course:
                course

        });

    }
);


app.delete(
    "/api/courses/:id",
    (req, res) => {

        const id =
            Number(req.params.id);

        const index =
            courses.findIndex(
                item =>
                    item.id === id
            );

        if (
            index === -1
        ) {

            return res.status(404).json({

                success: false,

                message:
                    "Course not found."

            });

        }

        const deletedCourse =
            courses.splice(
                index,
                1
            )[0];

        res.json({

            success: true,

            message:
                "Course deleted successfully.",

            course:
                deletedCourse

        });

    }
);


app.get(
    "/health",
    (req, res) => {

        res.json({

            status:
                "ok",

            message:
                "Course API is running."

        });

    }
);


app.use(
    (req, res) => {

        res.status(404).json({

            success: false,

            message:
                "API route not found."

        });

    }
);


app.listen(
    3000,
    () => {

        console.log(
            "Course API running on port 3000"
        );

    }
);

Step 3: Test All APIs

Get All Courses

GET /api/courses

Get One Course

GET /api/courses/1

Create Course

POST /api/courses

JSON:

{
    "name": "Data Analytics",
    "duration": "4 Months",
    "fee": 20000
}

Update Course

PUT /api/courses/1

JSON:

{
    "name": "Advanced Python",
    "duration": "4 Months",
    "fee": 18000
}

Delete Course

DELETE /api/courses/2

Health Check

GET /health

Project Flow

Client
   ↓
HTTP Request
   ↓
Express.js
   ↓
Route
   ↓
Validation
   ↓
Business Logic
   ↓
Data Storage
   ↓
JSON Response

What You Practiced

This project combines several real-world concepts:

  • Express.js
  • REST APIs
  • Routing
  • Route parameters
  • Request bodies
  • Validation
  • CRUD operations
  • HTTP status codes
  • JSON responses
  • Error responses
  • Health checks
  • 404 handling

Key Takeaways

1. Real-world Node.js means solving practical problems

Node.js is commonly used to build APIs, backend applications, automation tools, file-processing services, and web applications.

2. Express.js is useful for building APIs

Express provides routing, middleware, request handling, and response handling.

3. Always validate incoming data

Never assume that data from a client is correct.

4. Use appropriate HTTP status codes

Common status codes include:

200 OK
201 Created
400 Bad Request
401 Unauthorized
404 Not Found
409 Conflict
500 Internal Server Error

5. Use middleware for repeated logic

Authentication, logging, validation, and error handling can often be implemented through middleware.

6. Do not store important data only in arrays

Arrays are useful for learning but are not suitable as the primary storage mechanism for most production applications.

7. Databases provide persistent storage

Use MongoDB, PostgreSQL, MySQL, or another suitable database for production data.

8. Keep secrets outside your source code

API keys, database passwords, JWT secrets, and other sensitive configuration should normally be stored using environment variables or a dedicated secrets-management system.

9. Centralized error handling improves API quality

A common error handler provides consistent responses and makes debugging easier.

10. File uploads require security checks

Check file size, type, storage location, and access rules before accepting uploaded files.

11. Search and pagination improve large APIs

Query parameters can be used to search, filter, sort, and paginate resources.

12. Health checks help monitor applications

A /health endpoint can quickly indicate whether an application process is responding.

13. Use meaningful API URLs

Prefer resource-oriented endpoints such as:

/api/users
/api/courses
/api/products

instead of unclear URLs.

14. Separate application responsibilities

As an application grows, separate:

Routes
Controllers
Services
Models
Middleware
Configuration

15. Authentication and authorization are different

Authentication answers:

Who are you?

Authorization answers:

What are you allowed to do?

16. Test APIs before connecting a frontend

Tools such as Postman, Insomnia, or similar API clients can help you test endpoints independently.

17. REST APIs should return predictable responses

A consistent JSON response structure makes APIs easier for frontend and mobile developers to consume.

18. Logging is important in production

Useful logs can help developers understand errors, requests, and application behavior.

19. Environment-specific configuration is important

Development, testing, and production environments may require different database URLs, ports, API keys, and other configuration values.

20. Build projects instead of only reading theory

Projects such as Todo APIs, Course APIs, Student APIs, Product APIs, and Expense APIs help turn Node.js concepts into practical development skills.

FAQs

1. What are real-world Node.js projects?

Real-world Node.js projects are applications that solve practical problems using Node.js. Examples include REST APIs, authentication systems, course management systems, ecommerce backends, file-upload services, dashboards, and database-driven applications.

2. Is Node.js suitable for real-world applications?

Yes. Node.js is widely used for backend services, APIs, web applications, real-time applications, automation, and other server-side workloads.

3. What should I build to practice Node.js?

Beginners can start with:

  • Todo API
  • Student Management API
  • Course Management API
  • Product API
  • Blog API
  • Expense Tracker API

After that, add authentication, databases, validation, file uploads, and role-based access.

4. Should I use MongoDB or MySQL with Node.js?

Both can work well. MongoDB is a document database, while MySQL is a relational database. The better choice depends on your application’s data structure, relationships, queries, team experience, and project requirements.

5. How do I make a Node.js project production-ready?

A production application usually needs more than basic API routes. Important areas include validation, authentication, authorization, database design, secure configuration, error handling, logging, testing, monitoring, rate limiting, and secure deployment.

6. Why should Node.js projects use environment variables?

Environment variables allow configuration and sensitive values to stay outside the source code.

For example:

PORT=3000
DATABASE_URL=your-database-url
JWT_SECRET=your-secret

They help keep configuration different between development, testing, and production.

7. What is the best way to learn Node.js through projects?

Learn one concept and immediately use it in a small project. Start with a basic API, then add CRUD operations, validation, database integration, authentication, error handling, file uploads, testing, and deployment. This gradually takes you from beginner-level Node.js to practical backend development.

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top