𝗖𝗹𝗲𝗮𝗻 𝗔𝗣𝗜 𝗗𝗲𝘀𝗶𝗴𝗻 𝗶𝗻 𝗡𝗼𝗱𝗲.𝗷𝘀
Most Node.js APIs start with a single server.js file and a few routes. This works when the app is small.
Then the app grows.
Routes multiply. Business logic leaks into route handlers. Error handling becomes a mess of copy-pasted code. New developers struggle to find where things live. The API still works, but it becomes hard to maintain.
Clean API design prevents this. You need a structure that separates concerns.
Here is how to build a professional API layer by layer:
- Project Structure: Use feature folders. Every domain should own its router, controller, service, and schema.
- Versioning: Start with /api/v1/ from day one. Adding v2 later should be a folder move, not a full refactor.
- The Controller Layer: Controllers handle HTTP. They translate requests into service calls and send responses. They do not contain business logic.
- The Service Layer: This is where your business logic lives. Services should not know about req or res objects. They only care about data and rules.
- Validation: Use Zod at the boundary. Validate inputs before they ever reach your controllers. This prevents malformed data from breaking your logic.
- Centralized Error Handling: Use one single error handler for the entire app. This ensures every error response has the same structure.
- Consistent Responses: Use a helper to shape your success and error responses. Predictable JSON makes life easier for frontend developers.
- Rate Limiting: Protect your endpoints from abuse with middleware.
- Documentation: Use Swagger to generate interactive API docs automatically.
Why this matters:
When you separate these layers, you gain flexibility. If you need to switch from a mock database to a real one, you only change the service. The controllers and routers remain untouched.
If you want better performance and built-in TypeScript support, consider Fastify. The structural principles remain the same, but the framework handles more for you.
Stop putting everything in one file just for now. Building a proper structure early is not overengineering. It is the minimum requirement for a maintainable backend.
What does your current Express setup look like? Do you use a layered architecture or an organic one?
Source: https://dev.to/gavincettolo/clean-api-design-in-nodejs-a-practical-guide-3a32