Backlinks Graph
Backlinks
Table of Contents

Tao of Node

  2026-02-09

  Edited: 2026-02-09

Introduction

Taken from here. I find this to be a great resource and agree with many of its recommendations.

Architecture

Services, Routes, Handlers

Break logic up for the backend. This is mainly for routes. Group the logic into the domain they operate one. So you would have for example a users/ directory and an organizations/ directory containing user logic and organization logic. In each folder you would have at the minimum

This is different from the usual separation of all routes in a routes/ directory and all services in a services/ directory.

Here are some examples of a possible setup

// user-service.js
// snip..
export async function registerUser(userid, name, password) {
    // Do database queries or modifications ...
}
// snip..

// user-hander.js
// snip...
export async function registerUser(req, res) {
    const { error, value } = schema.validate(req.body);
    service.registerUser(value.name, value.password);
}
// snip..
// user-routes.js
// snip...
router.post('/user', hander.registerUser);
// snip...

Pretty clean.

Data

You can use a repository to fetch data and then use a DAO to map repository data into your data. I find this part optional, since if its data you control or the data exactly matches your requirements, having a DAO is just an unnecessary layer of abstraction. However, having something like a repository is useful, for both fetching and modifying the data, though it can be fulfilled by something like a Mongoose Schema Model.

Utility

You can put utility functions in the same directory as well. But separate it from global utilities which should be somewhere near the root of the project.

Validation

Validation is great and replaces a lot of the if statement checks, but most importantly, it serves as schema and documentation for the endpoints. When combine with something that auto-generates docs like OpenAPI it is awesome.

You can validate in an middleware or directly in handlers. I like it in middleware so you have centralized logic.

Logging

I like using a middleware which logs requests body, id, params, before a request gets executed. So using something like pino, the flow would be

Error Handling

Use a centralized error handler. This can be done in a middleware which runs after the routes middleware. In this module

And in the handlers, use next(...) to forward the error down instead of handling it on a handler by handler basis.

Other Stuff