Skip to content

Mean 03 Express Server Setup

DodaTech 4 min read

title: "Express Server Setup — Building the MEAN Backend API" description: "Set up an Express.js server for the MEAN stack with middleware, routing, error handling, and connection to MongoDB for full-stack JavaScript applications." weight: 13 date: 2026-06-28 lastmod: 2026-06-28 tags: [frameworks, mean]

Express.js is the backend framework for the MEAN stack. It handles HTTP requests, routing, middleware, and serves as the API layer between Angular and MongoDB.

What You'll Learn

You will create an Express server with middleware configuration, route structure, error handling, and MongoDB connection.

Why It Matters

Express is the backbone of the MEAN stack. A well-configured server with proper middleware and error handling saves hours of debugging later.

Real-World Use

DodaZIP's file management API uses Express with custom middleware for authentication, logging, file upload handling, and rate limiting.

flowchart LR
    A[Client Request] --> B[Express Middleware]
    B --> C[CORS]
    B --> D[JSON Parser]
    B --> E[Auth Check]
    C --> F[Route Handler]
    D --> F
    E --> F
    F --> G[Database Query]
    G --> H[JSON Response]
    style B fill:#4a90d9,color:#fff
    style F fill:#4a90d9,color:#fff

Creating the Express Server

Start by creating the main server file with Express configuration.

// backend/server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
require('dotenv').config();

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

// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// MongoDB Connection
mongoose.connect(process.env.MONGODB_URI)
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.error('MongoDB connection error:', err));

// Basic route
app.get('/api/health', (req, res) => {
  res.json({ status: 'OK', timestamp: new Date().toISOString() });
});

// Start server
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Expected output: The server starts on port 3000, connects to MongoDB, and provides a health check endpoint. Accessing GET /api/health returns {"status": "OK", "timestamp": "2026-06-28T..."}.

Route Structure

Organize routes into separate files for maintainability.

// backend/routes/userRoutes.js
const express = require('express');
const router = express.Router();

router.get('/', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

router.post('/', async (req, res) => {
  try {
    const user = new User(req.body);
    await user.save();
    res.status(201).json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

module.exports = router;
// backend/server.js — using the routes
const userRoutes = require('./routes/userRoutes');
app.use('/api/users', userRoutes);

Expected output: Routes are organized in separate files. The route module exports a router that is mounted on a base path in the main server file.

Error Handling Middleware

Create a centralized error handler for consistent error responses.

// backend/middleware/errorHandler.js
function errorHandler(err, req, res, next) {
  console.error(err.stack);

  if (err.name === 'ValidationError') {
    return res.status(400).json({
      error: 'Validation Error',
      details: err.message
    });
  }

  if (err.name === 'CastError') {
    return res.status(400).json({
      error: 'Invalid ID format'
    });
  }

  res.status(err.status || 500).json({
    error: err.message || 'Internal Server Error'
  });
}

module.exports = errorHandler;

Usage in server.js:

const errorHandler = require('./middleware/errorHandler');
app.use(errorHandler); // Must be after routes

Expected output: All errors pass through the centralized error handler. Validation and cast errors return appropriate status codes and messages.

Common Mistakes

  1. Not placing error middleware last: Error handling middleware must be defined after all routes. Otherwise, it never catches route errors.

  2. Forgetting to call express.json(): Without this middleware, req.body is undefined for POST and PUT requests.

  3. Not handling MongoDB connection errors: If the database connection fails, the server should log the error and retry or exit gracefully.

  4. Exposing stack traces in production: The error handler should only return detailed errors in development. In production, return generic messages.

  5. Not using environment variables for configuration: Hardcoding port, database URI, and secrets is a security risk and makes deployment difficult.

Practice Questions

  1. What does express.json() middleware do?

It parses incoming JSON request bodies and makes them available at req.body.

  1. Why should error handling middleware be defined last?

Express runs middleware in order. Error handling middleware must be after all routes to catch errors from any route.

  1. How do you organize routes in Express?

Create separate route files using express.Router() and mount them on base paths in the main server file.

  1. What is the purpose of the cors middleware?

It enables cross-origin requests from the Angular frontend running on a different port.

  1. How do you access environment variables in Express?

Using process.env.VARIABLE_NAME after loading the dotenv package.

Challenge

Create an Express server with three route modules (users, products, orders), CORS configuration, JSON body parsing, and a centralized error handler that handles validation errors, cast errors, and generic errors differently.

Frequently Asked Questions

Can I use Express with TypeScript?

Yes. Install TypeScript and @types/express. Configure tsconfig.json and use ts-node for development.

How do I handle file uploads in Express?

Use multer middleware. It parses multipart/form-data and makes files available at req.files.

Should I use app.get or router.get?

Use router.get in route modules. Use app.get only in the main server file for top-level routes.

How do I secure the Express API?

Use helmet for security headers, rate limiting with express-rate-limit, input validation, and authentication middleware.

What is the difference between app.use and app.get?

app.use mounts middleware for all HTTP methods. app.get handles only GET requests. app.post handles only POST requests.

Mini Project

Build an Express server with CORS, JSON parsing, a health check endpoint, user and product route modules, and a centralized error handler. Test all endpoints with a REST client.

What's Next

Connect Express to MongoDB Atlas Connection for a production database.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro