Scalable microservices in Node using Nest.JS

Felipe Marques
Webera
Published in
6 min readDec 16, 2021

--

Hi guys, I hope you all are ok, today I would like to share with you something that we have been working on for some time and learning a lot about applying clean architecture to our microservices.

Before getting into the code, let’s understand how microservices work and organize our code, thus making services increasingly independent of frameworks, easily testable, regardless of the user interface, that is, the user interface can change at will without this reflecting in the rest of the application, be database-independent, as it maintains all business rules in the application itself, and, finally, be independent of any external agent, as the business rules do not “see” the “outside world “.

What is a microservice?

Microservice is an architecture that seeks to isolate each feature of a given system, transforming them into loosely coupled services with the possibility of independent deployment.

Microservices architecture emerged as a solution for monolithic web applications. In monolithic applications, everything is built-in units, the entire business rule is defined and grouped into one comprehensive application, updating a codebase in a microservices architecture can become quite complicated as it affects the entire system, even the smallest changes may be necessary to build and deploy a new version of the system.

We now know that microservices solve the problems of monolithic systems by segregating application modules (features) into smaller parts.

And when should we use microservices architecture?

Both architectures have their advantages and disadvantages, although the microservices architecture will solve the problem of speeding up the development of complex systems, there is no clear answer on when to use them. With microservices and decoupling, developers end up gaining flexibility that would otherwise be impossible with a monolithic architecture.

Monolithic applications end up being difficult to scale out, as every application needs to be replicated, this ends up being more difficult if an application depends exclusively on a single database. Microservices, on the other hand, can be scaled or duplicated depending on individual services. If you need to send more emails, just scale the microservice that takes care of email functionality.

If you need to implement the microservices architecture, ask the following question: Are there any problems with my monolithic application? If you have any issues, you may need to consider switching to microservices. If not, then persist — there is no need to invest time to solve a problem that does not exist.

The Disadvantages of microservice

Microservice architecture is not a magic solution that solves all your problems, it also has its drawbacks. Some of these disadvantages are:

  • Since different services use different databases, transactions involving more than one service need to use eventual consistency.
  • The perfect division of services is very difficult to achieve on the first attempt and needs to be iterated over before reaching the best possible separation of services.
  • As services communicate through the use of network interaction, this slows down the application due to network latency and slow service.

Why NestJs for microservices?

When creating a microservice, there are several major programming languages ​​to choose from with robust frameworks. NestJs has many tools for us to create a robust, organized, and testable application. A highlight is a power of dependency injection that the framework brings, where we can inject a module into another one, facilitating code reuse. But it’s worth noting that when this dependency injection makes modules dependent on each other, we hurt some Clean Architecture concepts.

The project that we will create next came from an idea of ​​experimenting with the development of an API that is able to keep its input interface, responses, and business rules highly independent of databases and frameworks.

Creation of our microservice

We’ll start creating our microservice thinking about a problem that it can solve so it’s easier to define the functionality that we’ll work on. The communication protocol that we will implement is TCP, which will be responsible for operations and we will use PacketSender for testing purposes, an open-source application that allows us to send network packets that support TCP.

Implementing a microservice via HTTP would be no different than implementing an API using Node.JS just because a microservice has a well-defined architecture and scope, so we will choose to use an asynchronous pattern with TCP packets which we will communicate with our microservice, and hence the choice of Nest.JS as it has many built-in features making it easier for us to create a microservices architecture.

We’re going to divide the development into four stages so this tutorial doesn’t get too extensive, they are:

  • Microservice structure and configuration
  • Creating a message pattern to communicate with the microservice
  • Performing microservice tests using PacketSender
  • We leave this step as the icing on the cake in the end I’ll tell you what’s next in the next chapter 😄

Microservice structure and configuration

In this step we will create a new application in NestJS using your CLI using the command below:

npx @nestjs/cli new products-microservice

Note: if you do not have npx installed, go to the link https://www.npmjs.com/package/npx

Now that your app has been created, make sure you are at the root of the project and install a library @nestjs/microservices.

cd products-microservice && yarn add @nestjs/microservices

We need to modify the main.ts leaving as the code snippet below:

NestJS supports several built-in transport layer implementations. The code above will create a microservice that communicates through the TCP transport layer to port 8080.

We have the option of using a message pattern or an event pattern to communicate with the microservice.

The message pattern acts as a request-response method, it is recommended for exchanging messages between services and the event pattern for when you just want to post events without waiting for a response.

We will just implement the functionality that will create a product based on the given input and we will get the created product. So let’s register a named message pattern create_product in the file app.controller.ts.

Next, we will abstract the logic of creating a new product, it can be implemented in different ways based on the needs and the database used, and we will focus only on requirements related to microservices.

The payload we use to create a new product will look like this:

And finally, the most important thing is our service, which will be responsible for saving this data in the bank.

With all our code created we can perform the test in our application using PackatSender.

Performing microservice tests using PacketSender

Now that we have our microservice configured and structured we need to perform the test to check if everything is working, for that we will use PacketSender to send a TCP packet to our application. Set the Address and Port to 127.0.0.1:8080 and select TCP from the drop-down menu on the right. To encode our message, use the ASCII field and fill it in with the following value:

122#{"pattern":"create_product",
"data":{"name":"G Suite","price":120},
"id":"ce51ebd3-32b1-4ae6-b7ef-e018126c4cc4"}
  • pattern- is the message we define in our microservicecreate_product,;
  • data- is the JSON object we want to send, an object with a nameand price;

The value 122 represents the length of our message starting from the first key to the last (both included).

References

Conclusion

The NestJS provides the possibility to build lightweight, well-structured and amazing microservices. Out-of-the-box tools and features make development, extension, and maintenance nice and efficient.

--

--