Project Structure: Scalable Architecture for REST APIs
MVC architecture, controllers, routes, models, services, middleware folder, project structure, separation of concerns, asyncHandler
Project Structure: Scalable Architecture for REST APIs
The way you structure your REST API project determines how easy it is to maintain, test, and onboard new developers. A flat pile of files in one directory works for a tutorial but falls apart in production.
The MVC-Inspired Layer Architecture
Professional REST APIs separate concerns into distinct layers. The route layer defines URL paths and maps them to controllers. The controller layer handles request parsing and response formatting. The service layer contains business logic. The model layer defines data schemas and handles database operations. Middleware handles cross-cutting concerns like auth, validation, and logging.
Recommended Directory Structure
src/
config/
database.js
middleware/
auth.js
validate.js
errorHandler.js
modules/
users/
user.routes.js
user.controller.js
user.service.js
user.model.js
user.validation.js
utils/
AppError.js
asyncHandler.js
index.js
app.jsThe asyncHandler Utility
Async route handlers need try-catch blocks in every function. An asyncHandler wrapper eliminates the repetition:
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);Wrap every async controller: router.get('/', asyncHandler(getAllUsers));. Any unhandled promise rejection is automatically forwarded to the error handling middleware.
Custom AppError Class
class AppError extends Error {
constructor(message, statusCode, code) {
super(message);
this.statusCode = statusCode;
this.code = code;
this.isOperational = true;
}
}The isOperational flag lets your error handler distinguish between expected operational errors (404, 403, validation failures) and programmer bugs (null references, type errors).
