DEV Community

Cover image for Building microservices with Node.js
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

Building microservices with Node.js

Written by Frank Joseph✏️

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.

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:

node -v
Enter fullscreen mode Exit fullscreen mode

If Node.js is not installed, go ahead and download it. In weathermicroservice, run the command below to initialize the package.json:

Run npm init or npm init -y
Enter fullscreen mode Exit fullscreen mode

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:

run npm install Express nodemon request
Enter fullscreen mode Exit fullscreen mode

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

Package JSON Node Microservice

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

// 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);
});
Enter fullscreen mode Exit fullscreen mode

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:

// 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);
};
Enter fullscreen mode Exit fullscreen mode

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:

// 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;
Enter fullscreen mode Exit fullscreen mode

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:

// 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;
Enter fullscreen mode Exit fullscreen mode

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 ✔️ 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.

LogRocket Sign Uphttps://logrocket.com/signup/

LogRocket 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.

Top comments (1)

Collapse
 
parashistik profile image
Parashistik • Edited

Thank you so much for this informative article. I recently became interested in node.js and was just looking for information on how to build microservices. By the way, I've learned a lot about cloud application development on this site, and in the future I intend to study this topic even more. I really like programming and computer science, and I constantly follow new technologies. And cloud technologies are the future.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.