Posted by Kosal
In 2025, building efficient and scalable RESTful APIs remains a cornerstone of modern web and mobile application development. Among the many tools available, Node.js and Express continue to stand out for their simplicity, speed, and vast ecosystem. Whether you're a seasoned backend engineer or just stepping into API development, this guide will walk you through creating a robust RESTful API using the latest patterns and best practices.
Node.js, powered by V8, is still one of the fastest JavaScript runtimes available. Its event-driven, non-blocking I/O model makes it ideal for building APIs that can handle thousands of simultaneous connections.
Express remains the most popular framework for creating web APIs with Node.js. It offers:
mkdir node-api-2025
cd node-api-2025
npm init -y
Install dependencies:
npm install express
npm install --save-dev nodemon
Update your package.json
to include a start script:
"scripts": {
"start": "nodemon index.js"
}
Create index.js
:
const express = require('express');
const app = express();
app.use(express.json()); // To parse JSON bodies
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Welcome to the User API!');
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Run the server:
npm start
When you run npm start, which launches the Express server, navigating to http://localhost:3000 will respond with:
Welcome to the User API!
We'll now implement full CRUD (Create, Read, Update, Delete) operations for managing users. For simplicity, this example uses an in-memory array instead of a real database.
Here’s the sample user object structure:
{
id: 1,
name: "Kosal Ang",
email: "angkosal@example.com"
}
Start by defining a mock database:
let users = [
{ id: 1, name: 'Bora Ang', email: 'bora@example.com' },
{ id: 2, name: 'Sakni Ang', email: 'sakni@example.com' }
];
Purpose: Retrieve a list of all users.
app.get('/api/users', (req, res) => {
res.json(users);
});
This endpoint returns the entire list of users. Useful for dashboards, admin panels, or lists in your frontend application.
Purpose: Retrieve a specific user by their id
.
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id == req.params.id);
if (!user) return res.status(404).json({ message: 'User not found' });
res.json(user);
});
This endpoint is useful when viewing a specific user's profile or editing their details. It checks whether a user with the provided id
exists and returns a 404 error if not.
Purpose: Add a new user to the system.
app.post('/api/users', (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({ message: 'Name and email are required' });
}
const newUser = {
id: users.length ? users[users.length - 1].id + 1 : 1,
name,
email
};
users.push(newUser);
res.status(201).json(newUser);
});
This endpoint handles user creation. It validates input and assigns a unique id
to each new user.
Purpose: Modify the name or email of an existing user.
app.put('/api/users/:id', (req, res) => {
const user = users.find(u => u.id == req.params.id);
if (!user) return res.status(404).json({ message: 'User not found' });
const { name, email } = req.body;
user.name = name ?? user.name;
user.email = email ?? user.email;
res.json(user);
});
Use this endpoint when users need to update their profile information. If the user doesn’t exist, it returns a 404. Only updates fields that are provided.
Purpose: Permanently remove a user from the system.
app.delete('/api/users/:id', (req, res) => {
const userIndex = users.findIndex(u => u.id == req.params.id);
if (userIndex === -1) return res.status(404).json({ message: 'User not found' });
users.splice(userIndex, 1);
res.status(204).send();
});
This endpoint is used to delete users who are no longer needed in the system. It ensures that the user exists before attempting to remove them.
Use Postman or curl to test your endpoints:
http://localhost:3000/api/users
You should get the following JSON response:
[
{
"id": 1,
"name": "Bora Ang",
"email": "bora@example.com"
},
{
"id": 2,
"name": "Sakni Ang",
"email": "sakni@example.com"
}
]
Or test each CRUD operation using appropriate HTTP methods like GET
, POST
, PUT
, and DELETE
.
Add centralized error handling middleware at the bottom of index.js
:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: 'Internal Server Error' });
});
Logging middleware:
app.use((req, res, next) => {
console.log(`${req.method} ${req.path}`);
next();
});
Enhance your API further with:
Building RESTful APIs with Node.js and Express in 2025 is as practical and powerful as ever. With minimal setup and rich extensibility, Express is a solid choice for both quick prototypes and production-grade APIs.