DEV Community

Free Tech Learner
Free Tech Learner

Posted on Originally published at freetechlearner.com

How to Build a REST API with Node.js and Express in 10 Minutes

Building a REST API with Node.js and Express is a rite of passage for modern web developers. Whether you are powering a mobile app or a single-page frontend, Express provides the lightweight, unopinionated framework needed to get a production-ready server running in minutes. In this guide, you will learn how to initialize a project, structure your routes, and implement full CRUD operations using the latest industry standards.

Why Choose Node.js and Express in 2025?

Node.js remains a top choice for backend development due to its non-blocking I/O model and vast ecosystem. Express, specifically with the recent release of Express 5.0, continues to dominate the market by offering a stable, predictable environment for routing and middleware.

While frameworks like NestJS offer more "batteries-included" features, Express is ideal for developers who want total control over their architecture. Building a REST API with Node.js and Express allows for rapid prototyping without the overhead of heavy boilerplate code.

Prerequisites and Environment Setup

Before we start the clock, ensure you have the following installed:

  • Node.js (v18.0 or higher): Express 5 requires modern Node.js versions for better performance and security.
  • npm or yarn: For package management.
  • A code editor: VS Code is the standard.

Open your terminal and create a new directory for your project:

mkdir fast-express-api
cd fast-express-api
npm init -y
Enter fullscreen mode Exit fullscreen mode

Next, install the essential dependencies. We will include express for the framework, dotenv for environment variables, and nodemon as a development dependency to auto-restart the server on code changes.

npm install express dotenv helmet
npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Configuring Your Project for Success

To use modern JavaScript features like import/export (ES Modules) instead of the older require syntax, open your package.json and add "type": "module" below the main entry point.

Your package.json should look like this:

{
  "name": "fast-express-api",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 1: Initialize the Express Server

Create a file named index.js in your root directory. This will be the entry point for your API. We will use Helmet middleware to automatically set secure HTTP headers, a crucial step for any production-ready API.

import express from 'express';
import helmet from 'helmet';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(helmet()); // Security
app.use(express.json()); // Body parser for JSON

// Basic Health Check Route
app.get('/', (req, res) => {
    res.json({ message: 'API is running smoothly' });
});

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 2: Designing the RESTful Routes

A standard REST API focuses on "Resources." In this example, our resource will be "Tasks." We need to support four primary actions: Create, Read, Update, and Delete (CRUD).

Instead of cluttering index.js, it is best practice to separate your logic into routes and controllers. For this 10-minute build, let’s create a mock database and implement the routes directly to demonstrate the flow.

Implementing CRUD Operations

Add the following code to your index.js (or a separate routes/taskRoutes.js file for better organization):

// Mock Database
let tasks = [
    { id: 1, title: 'Learn Express 5', completed: false },
    { id: 2, title: 'Build a REST API', completed: true }
];

// GET: Fetch all tasks
app.get('/api/tasks', (req, res) => {
    res.status(200).json(tasks);
});

// POST: Create a new task
app.post('/api/tasks', (req, res) => {
    const { title } = req.body;
    if (!title) {
        return res.status(400).json({ error: 'Title is required' });
    }
    const newTask = { id: tasks.length + 1, title, completed: false };
    tasks.push(newTask);
    res.status(201).json(newTask);
});

// PUT: Update an existing task
app.put('/api/tasks/:id', (req, res) => {
    const { id } = req.params;
    const { title, completed } = req.body;
    const taskIndex = tasks.findIndex(t => t.id === parseInt(id));

    if (taskIndex === -1) {
        return res.status(404).json({ error: 'Task not found' });
    }

    tasks[taskIndex] = { ...tasks[taskIndex], title, completed };
    res.json(tasks[taskIndex]);
});

// DELETE: Remove a task
app.delete('/api/tasks/:id', (req, res) => {
    const { id } = req.params;
    tasks = tasks.filter(t => t.id !== parseInt(id));
    res.status(204).send();
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Modern Error Handling in Express 5

One of the most significant updates in Express 5 is how it handles asynchronous errors. In older versions, you had to wrap every async route in a try/catch block or a wrapper function. Now, if a promise is rejected, Express 5 will automatically pass the error to your error-handling middleware.

Add this centralized error handler at the bottom of your index.js file:

// Global Error Handler
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({
        error: 'Something went wrong!',
        message: err.message
    });
});
Enter fullscreen mode Exit fullscreen mode

Best Practices for Scaling Your API

While you can build a REST API with Node.js and Express in under 10 minutes, maintaining it requires a more structured approach. Consider these three pillars as your project grows:

  1. Environment Isolation: Use .env files for database credentials and API keys. Never hardcode these values in your repository.
  2. Validation Middleware: Use libraries like joi or express-validator to ensure the data coming into your POST and PUT requests is clean and expected.
  3. Controller Pattern: Move your route logic out of the route definition.
    • routes/: Define the endpoints and link them to controllers.
    • controllers/: Handle the business logic and interact with the database.
    • models/: Define your data structures (e.g., using Mongoose for MongoDB or Sequelize for SQL).

Testing Your New API

To test your API, you don't necessarily need a frontend. You can use tools like:

  • Postman or Insomnia: The industry standard for GUI-based API testing.
  • Thunder Client: A lightweight VS Code extension that lives inside your editor.
  • cURL: For quick terminal-based testing.

To test your GET endpoint with cURL, run:

curl http://localhost:3000/api/tasks
Enter fullscreen mode Exit fullscreen mode

To test your POST endpoint:

curl -X POST http://localhost:3000/api/tasks \
     -H "Content-Type: application/json" \
     -d '{"title": "Master Node.js"}'
Enter fullscreen mode Exit fullscreen mode

FAQ: Frequently Asked Questions

Is Express 5 significantly different from Express 4?

Express 5 is mostly a refinement of Express 4. The biggest changes include better handling of rejected promises in async routes, the removal of outdated methods like app.del() (use app.delete() instead), and stricter requirements for Node.js versions.

How do I connect a database like MongoDB to this API?

You would typically use an ODM like Mongoose. You would initialize the connection in your index.js and then replace the mock tasks array logic with asynchronous database queries (e.g., const tasks = await Task.find()).

Should I use TypeScript with Express?

For small projects or rapid prototyping, JavaScript is faster. However, for enterprise-level APIs, TypeScript is highly recommended as it provides type safety, which prevents common bugs and improves the developer experience in large codebases.

Conclusion

Building a functional REST API with Node.js and Express is a streamlined process that prioritizes speed and developer freedom. By leveraging Express 5 and modern ESM syntax, you’ve created a secure, scalable foundation for any web application in just a few minutes.

Your next step is to replace the mock data with a real database like PostgreSQL or MongoDB and implement JWT (JSON Web Tokens) for authentication. As your API grows, keep your code modular and your dependencies updated to maintain high performance.

Originally published at freetechlearner.com

Top comments (0)