Mean 03 Express Server Setup
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
Not placing error middleware last: Error handling middleware must be defined after all routes. Otherwise, it never catches route errors.
Forgetting to call express.json(): Without this middleware, req.body is undefined for POST and PUT requests.
Not handling MongoDB connection errors: If the database connection fails, the server should log the error and retry or exit gracefully.
Exposing stack traces in production: The error handler should only return detailed errors in development. In production, return generic messages.
Not using environment variables for configuration: Hardcoding port, database URI, and secrets is a security risk and makes deployment difficult.
Practice Questions
- What does express.json() middleware do?
It parses incoming JSON request bodies and makes them available at req.body.
- 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.
- 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.
- What is the purpose of the cors middleware?
It enables cross-origin requests from the Angular frontend running on a different port.
- 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
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