Building REST APIs with Node.js and Express.js
A practical guide to structuring production-ready REST APIs with Node.js and Express.js: routing, validation, error handling and security.
Express.js is still one of the most popular ways to build APIs in Node.js. It is small and flexible, but that flexibility means structure is up to you. Here is the structure I use for production APIs.
Separate routes, controllers and services
Keep each layer focused. Routes map URLs and middleware, controllers parse the request and send the response, and services contain business logic and database access. Services never touch req or res, which makes them easy to test and reuse.
router.get("/projects/:id", authenticate, projectController.getById);Validate every input
Never trust request data. A schema library such as Zod validates the body, params and query and gives you typed data in one step. Invalid input should return a 400 with field-level errors the client can display.
Centralize error handling
Throw typed errors from services (for example NotFoundError) and convert them in a single error-handling middleware. Every response then has the same shape, and unexpected errors never leak stack traces to clients.
Secure by default
- Use Helmet for security headers and restrict CORS to known origins
- Rate-limit authentication and public form endpoints
- Hash passwords with bcrypt and keep tokens in HTTP-only cookies
- Use an ORM or parameterized queries to prevent SQL injection
Conclusion
A clear layered structure, strict validation and consistent errors make an Express API easy to extend and safe to run in production.