Clean Architecture design in NodeJS

NodeJS is one of the core technologies that we use in SolidGEAR to bring our applications to life. But as almost every technology available out there, the most critical part is not about the technology itself but how we use it to accomplish our goals. Therefore, this post tries to gather all the experience earned by us working with NodeJS to define a good and tested architecture, based mostly in concepts like ‘Clean Architecture‘ and ‘Hexagonal Architecture‘, so that you’ll be able to follow it and design your backend in a way that it can adapt to most projects and scale in an appropriate way.

Blocks Ready - Clean Architecture

This is not the ultimate guide to design foolproof applications. There’s surely a lot of improvements that can be applied, specially regarding to the needs of each project. But you can take advantage of our previous work and several years of testing this architecture to avoid some problems and headaches while being in the middle of a project that has evolved in an unexpected way for you.

Hidden problems behind some NodeJS architectures

Let’s start designing a NodeJS architecture on our own. Most concepts can be extrapolated to other backend technologies, but let’s focus on this one. We’ll choose Express as the API framework (based on REST) and MongoDB (using Mongoose) for the database, because MEAN stack has become widely mainstream for the last few years. Nevertheless, concepts addressed in this section are transparent to the technology stack chosen.

An example of a basic NodeJS server can be seen in this link, which basically has a resource to allow us to create a new ‘user’:

This server has several good ideas behind. It has separated layers for handling API requests and db queries. Separated files for modules of REST resources and also for db modules (although just a single module of users management has been added for this example). It looks like it can escalate smoothly as the quantity and complexity of resources increase, but that’s not quite true.

Hidden hedgehog

Let’s assume that we have to add a new resource in our server to create a group. A group is designed to contain users. But our business logic determines that a group should create a default user that will be in charge of managing the group. First steps are quite easy to implement, as we can see here:

But how are we going to reuse our previous code for creating the user?

Importing the method in ‘routes’ layer is annoying, because we need to start passing express linked objects (‘req’, ‘res’,…) from one place to another. Importing the method in ‘db’ layer is inaccurate because we’re missing strategically added functionality in the ‘routes’ layer (setting the completeName of the user).


Moreover, let’s consider that we are going to add some unit tests (because of course, we want unit tests in our code) to our current functionality. Tests for our ‘routes’ domain wouldn’t be a bit express-linked? If we move to a, for example, GraphQL API, will we have to rewrite them all?

How would you solve these problems? Splitting the current methods? Creating a new layer? Maybe creating several new layers?

Do not reinvent the wheel. Clean Architecture + Hexagonal Architecture

We are not unveiling a trailblazer solution. We have just evaluated the best current architecture models available right now and adapted them to our needs.

So we started analysing one of the most known architecture pattern, the one proposed by Uncle Bob some years ago, called Clean Architecture. It supports the idea of making the model independent from the framework, libraries, dbs… (seems logic, doesn’t it?), by creating an intermediate layer called ‘Interface adapters‘. He also remarks the necessity of the code to be easily testable, and how this kind of architecture will allow us to create unit tests of the code not linked to any external technological element.

Additionally, we analysed another great and widely used architectural model, the Hexagonal Architecture proposed by Alistair Cockburn in 2005. Different geometric shapes, but very similar concepts. Enclose your app functionality to be used for any outsider through a system of ports and adapters.

Matching pieces. Clean Architecture + Hexagonal

So following those rules we split all the business logic from our API framework, creating a new ‘domain’ layer:

Achieving this way:

  1. Our domain code is reusable and independent from our API framework
  2. The code is also easily testable and tests can survive through frameworks and libraries changes.

And we can see in the final example version how the core functionality remains unchanged, although we have added a new GraphQL based API that makes use of the same domain methods. On top of that, we have created some unit tests that assure the correct functioning of our business logic autonomously, whatever the API framework is used.

Further improvements


As we have stated previously, this is just a base architecture on top of which you should adapt your project’s needs. Also, as we don’t want this post to be humongous, we are not going to detail any of the followings improvements, but it’s the duty of the advanced reader to take this issues also in consideration. (And you can ask us for more info in the comments section below if you want)

  • Improve API adapters definition: Our REST API adapter unties our business logic from resources, requests, responses, and other REST stuff. But a more complete layer should include http codes mapping, i18n messages, and everything we need to exploit the full potential of the API protocol
  • Add adapter layer to db: In the same way we have split our API technology from our code, we should do the same with the db layer to make our application utterly independent of the db technology we are using. Likewise, we should add an adapter for every external framework we want to isolate from our domain code.
  • Define domain entities: Some Clean Architecture models talk about defining the core entities in our business logic and abstract them into a inner layer. That may depend on your application, but it’s something you should definitely consider if you are going to have some well defined entities along your application logic.

Ready for facing the challenge of having a scalable NodeJS server prepared to adapt every situation?

There’s something else you think that should be mandatory in a good NodeJS architecture?


If you want to know how to do your first API with NodeJS + Express (Spanish):

Related Articles

3 thoughts on “Clean Architecture design in NodeJS”

  1. You’re article is really great and this repository gives me some insight about Clean architecture. I recently read the Clean architecture book and I’m searching some sample projects in node.js which use the architecture then I find your awesome repo.

    Based on Clean architecture, we need to define some Interface adapter to communicate the infrastructure to use case layer. Javascript doesn’t have Interface, so how do you separate the interface to its implementation in Javascript? How about port and adapter, how do you deal with it?

    And also how do you define the entity? I would love to hear your suggestion.

    • Hi Dennis,

      first of all, thanks for your feedback.
      You brought up great questions, because they follow the proper path when trying to get deeper in the clean architecture model. I’ll try to answer them the best I can, based on our experience in projects with this architecture.

      Lack of interfaces in Javascript – 2 possible alternatives here. An interface is no more than a contract between 2 parts. This isn’t need to be defined at a code level. Documenting properly the code in a layer and how it has to be called from the external layers is the quickest and most effective way to handle it for small/medium size projects.
      But I know, this can be a great pain in the ass for huge projects, distributed teams.. so you can use an additional layer in top of JS to define your interfaces, like Typescript. There’re frameworks like Nest that can help you.

      Ports & Adapters – Controversial subject as it depends a lot on the scope and requirements of your projects. As a brief summary, ports can be understood as the interfaces in the model layer. So based on the previous point, defining the interface of this layer would be equivalent to defining the ports of your business logic.
      Regarding adapters, what we usually do is to create and intermediate layer between the model and the framework library. Like the db layer you can see in the example that links the model to the db framework. You can subdivide this generic ‘db’ folder into others more specific like: mongoDbAdapter, postgresqlAdapter, firebaseAdapter…

      Entity – Just add another layer with your domain entities. You can define Classes in JS, so basically do it and use these classes into the model layer.

      Adding more layers always increase the complexity of your project, so be always conscious of the scope of your project and be careful to not design an architecture more complex that it should be.


Leave a Comment

¿Necesitas una estimación?

Calcula ahora

Privacy Preference Center

Own cookies

__unam, gdpr 1P_JAR, DV, NID, _icl_current_language

Analytics Cookies

This cookies help us to understand how users interact with our site

_ga, _gat_UA-42883984-1, _gid, _hjIncludedInSample,

Subscription Cookies

These cookies are used to execute functions of the Web, such as not displaying the advertising banner and / or remembering the user's settings within the session.

tl_3832_3832_2 tl_5886_5886_12 tve_leads_unique