Building microservices with Node.js
Tags: node
Published: 2022-02-07 15:21:26

**Written by [Frank Joseph](https://blog.logrocket.com/author/frankjoseph/)✏️**

Early on in the practice of software development, best practice involved tightly coupling all of the software’s components in what is known as a monolithic application. However, monolithic applications require extra effort to respond to changes in the system. If any particular component develops a fault, the entire system is affected.

Nowadays, we can solve the problem using microservices, which allow us to build our software product components separately. If there is a fault in one component, it won’t affect the functioning of the entire software product.

In this article, we’ll review the concept of microservices, learn how to implement a microservice with Node.js, and explore how microservices are changing the practice of software development. Let’s get started!

### Prerequisites

To follow along with this article, you’ll need the following:

*   Node.js installed on your computer
*   Basic knowledge of JavaScript and Node.js

## Microservices vs. monolithic applications

### Understanding monolithic applications

A monolithic application is a single-tiered application in which all components are composed as one unit.

Imagine you’re building a library management system, and all of the components, like `books`, `users`, and their respective services and databases are fused together as one unit. If there is a fault in any one component, the entire system will need to be brought down to correct the error.

For this reason, monolithic applications are neither flexible nor easily scalable. You cannot build features concurrently or achieve continuous deployment. However, while monolithic applications are not cost-effective to manage, they are cost-effective to build. Developers recognized the need to create a system in which one faulty component wouldn’t affect the entire software system.

### Understanding microservices

Microservices became necessary due to the shortcomings of the monolithic pattern of software development. In a microservice, each software application feature is separated from the other, in most cases with their respective servers and databases. Applications built with this kind of architecture are loosely coupled, also referred to as distributed applications.

Imagine we're building an ecommerce store. We’ll need models for a `payment feature`, `cart`, `customers`, `admin`, and `order`. Each of these features will have its own separate servers and databases.

Our ecommerce microservices will communicate with each other using the REST API framework. With our store features developed independently from each other, we can easily identify which feature to debug if our system develops a fault and avoid having to bring down the entire application.

In contrast to monolithic applications, applications developed using microservices are scalable. You can use any programming language to develop a microservice; in fact, you can use different languages to develop different features in a microservice application.

Overall, microservices offer a better developer experience. A new developer joining the team won't have to understand the entire code base, but rather only the features they are working on, increasing productivity. Lastly, unit testing is encouraged in microservices. A unit test can be written to test a particular functionality.

However, it's important to keep in mind that building microservices requires expertise because integration and end-to-end testing can be very challenging. Additionally, microservices can become very bulky, causing high maintenance costs. Finally, it's not always easy to migrate software already developed using monolithic architecture to a microservice, and it can be challenging for applications to locate each other within a complex network.

## Using Node.js for our microservice

You can use any programming language, like Java, C#, or Python to develop a microservice, but Node.js is an outstanding choice for a few reasons.

For one, Node.js uses an event-driven architecture and enables efficient, real-time application development. Node.js single-threading and asynchronous capabilities enable a non-blocking mechanism. Developers using Node.js to build microservices have an uninterrupted flow, with Node.js code being fast, highly scalable, and easy to maintain.

## Build a simple microservice application with Node.js

To illustrate how to develop microservices with Node.js, we’ll use the OpenWeather API service. First, [create a free account](https://openweathermap.org/).

Create a new folder on your computer, preferably on your desktop for easy access, and name it `weathermicroservice`. Open `weathermicroservice` in your code editor and confirm you have Node.js installed on your computer by running the command below:

```BASH
node -v
```

If Node.js is not installed, [go ahead and download it](https://nodejs.org/en/download/). In `weathermicroservice`, run the command below to initialize the `package.json`:

```BASH
Run npm init or npm init -y
```

With `npm init`, you customize the setting or fields to create the `package.json` file. On the other hand, `npm init -y` uses the default setting or fields to create the `package.json` file.

Now, let’s install our required dependencies with the command below:

```BASH
run npm install Express nodemon request
```

Now, your `package.json` file should look similar to the screenshot below:

![Package JSON Node Microservice](https://blog.logrocket.com/wp-content/uploads/2022/01/package-json-node-microservice.png)

Directly inside the main folder, create a file called `server.js`. Inside, write the following code:

```js
// require express
const express = require("express");

//create an app using express constructor
const weatherApp = express();

// declare your port
const port = 5000;

// require routes from the routes.js file
const routes = require("./api/routes");
// set the route for our application by passing the app to the routes object
routes(weatherApp);

// call the listen method on the app
weatherApp.listen(port, ()=>{
    console.log("Server is running is port: " + port);
});
```

`server.js` is the main file for our microservice app, as indicated in our `package.json` file. Next, we’ll create another folder inside the `weathermicroservice` folder named `api_source`.

Inside the `api_source` folder, create two files named `controller.js` and `routes.js`. Inside the `routes.js` file, write the following code:

```js
// create a controller object
const controller = require("./controller");

// declare a function and export it to be used in another file
module.exports = function(weatherApp){
    weatherApp.route("/about")
                .get(controller.about);
    weatherApp.route("/weather")
                .get(controller.getWeather);
};
```

The function takes `weatherApp` as a parameter and defines the routes for our application. `weatherApp.route("/about")` listens for a `GET` request on the `/about` endpoint.

This request is then handled by the `about` function in the `controller.js` file. The `weatherApp.route("/weather")` listens for a `GET` request on the `/weather` endpoint. The `getWeather` function handles the request.

Now that we’re done with the `route` module, it’s time to create the controllers to handle the `GET` request from the `route` module. Inside your `controller.js` file, write the following code:

```js
// create a variable referencing to the package.json file
let properties = require("../package.json");

// create a variable and require the weather file inside the service folder
let weather = require("../service/weather");

// create an object
let controllers = {
    about: (req, res)=>{

//create an object and access the values in the package.json file
        let aboutInfo ={
            name: properties.name,
            description: properties.description,
            author: properties.author 
        }
// return the object in json format
        res.json(aboutInfo);
    },

//create a function
    getWeather: function(req, res){

//call the find method on the weather module
        weather.find(req, res, function(err, weath) {
            if(err)
                res.send(err);
             res.json(weath);
        });
    },
};

//export the controller module so it can be use in another file within the application
module.exports = controllers;
```

Inside the main folder, create another folder called `service`. Inside the `service` folder, create a file called `weather.js`, where we’ll connect to the external API.

Inside the `weather.js` file, write the following code:

```js
// declare the request package we added to the package.json
let request = require("request");

// assign your api key and api url to a variable
const apiKey = "your own api key";
const apiUrl = "your api url as provided on your dashboard";

let weather = {
    find: (req, res, next)=>{
        request(apiUrl + apiKey + "/weather.json" + req.params.weather,
        function(error, response, body){

//check that there is no error
            if(!error && response.statusCode==200){
                response = JSON.parse(body);
                res.send(response);
            }else{
                console.log(response.statusCode + response.body);
                res.send("An error occurred, it could be from your api");
            }
        });
    }
};

//export the weather module 
module.exports = weather;
```

In the code above, we use the `find` function, which accepts three parameters, `request`, `response`, and `next` objects. The `request` object in line 10 accepts the URL of the service and defines a callback function to handle the response.

## Conclusion

In this tutorial, we learned about the important differences between microservices and monolithic applications. We learned why Node.js is a great choice for building microservices, and we ran through an example using the OpenWeather API. Using a microservice offers flexibility and performance benefits that can't be achieved with a monolithic application. The event-driven architecture of Node.js makes it a perfect choice for microservices, being fast, highly scalable, and easy to maintain.

---
##200’s only :heavy_check_mark: Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, [try LogRocket.](https://logrocket.com/signup/)

![LogRocket Sign Up](https://blog.logrocket.com/wp-content/uploads/2019/12/network-request-filter-2-1.png)https://logrocket.com/signup/

[LogRocket](https://logrocket.com/signup/) is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. [Start monitoring for free.](https://logrocket.com/signup/)