Building Microservices with Node.js and gRPC

Introduction to Microservices and gRPC

Building and managing large applications is a complex task. To simplify this, companies often break down these applications into multiple microservices. These microservices are small, independently deployable, and loosely connected, making it easier for separate teams to manage different parts of the application. For effective communication between these microservices, gRPC is a popular choice due to its lightness, performance, and type safety. Developed by Google, it uses HTTP/2 for transport and Protocol Buffers to serialize structured data.

In this comprehensive blog, we will explore how to create microservices with Node.js and facilitate their communication using gRPC.

Setting Up the Repository for Microservices

To start, we'll create a new project repository, structure our workspace, and organize the services and packages. Our directory layout will include src, dist, protos, and service folders. The protos directory will be particularly important, as it will contain our Protocol Buffer (protobuf) files which define the structure of the data and services for gRPC.

Defining the Protobuf for the product-service

The product-service microservice will use a protobuf file namely product.proto. This file will define the data structures related to products such as Product, and services like ProductService with RPC methods CreateProduct, GetProduct, and ListProducts. The product.proto file provides the contract for data communication.

Generating Typescript Files from Protobuf

Once the protobuf file is ready, we'll need to transform these definitions into language-specific code. Using tools like ts-proto alongside protoc, we can generate TypeScript files that include type-safe stubs for client and server implementations. The build script we write will facilitate this process, ensuring that our dist directory contains the necessary JavaScript and type declaration files.

Creating the gRPC Server

The product-service needs a gRPC server. We will use Node.js and additional libraries like typeorm to integrate database operations. After setting up our package.json using npm init, we'll structure our server code within the src directory, including:

  • A models directory with a product.ts defining the product entity.
  • A database folder with an index.ts file to configure our data source.
  • The main.ts file, which will configure and start our gRPC server.

We need to install various dependencies and create the tsconfig.json file to compile TypeScript into JavaScript.

Implementing Server Functionality

Within the server implementation, located in server.ts, we'll create methods corresponding to the RPC services defined in our protobuf file. These methods include createProduct, getProduct, and listProducts. If a service is called but not implemented, the server responds with the status UNIMPLEMENTED.

By setting up controllers in src/controllers/product.controller.ts, we can handle incoming RPC requests. The ProductController class will contain methods like createProduct, which takes a CreateProductRequest from the client and converts it into a Product entity to be stored in the database.

Handling Errors and Feedback

Our server implementation needs to handle various scenarios, such as when a product is not found (NOT_FOUND) or when an internal server error occurs (INTERNAL). It also maps the data from our database into the structures defined in our protobuf file, ensuring the correct format when sending responses back to the client through methods like ListProducts and GetProduct.

Creating a gRPC Client

For testing our server, we create a gRPC client. Using npm init, we scaffold another package.json file in a test-client folder. After setting up tsconfig.json, we write a main.ts in the src folder to implement our client functionality using @grpc/grpc-js.

The client uses a ProductServiceClient to send requests to the server, invoking methods like createProduct, getProduct, and listProducts. We make sure to handle security by establishing the right credentials (in our case credentials.createInsecure() due to the local testing environment).


In conclusion, this blog provides a detailed walkthrough of setting up microservices in Node.js with gRPC communication. Using TypeScript and Protocol Buffers enhances the developer experience with type safety and contracts for data exchange. The system we've covered includes a server with CRUD operations for a product service and a corresponding client to interact with it.

Following this guide, developers can develop scalable microservices that communicate efficiently through gRPC, enjoying advantages like lightweight communication, improved performance, and the convenience of independent deployment and scalability.

Tags: #Nodejs, #Microservices, #gRPC, #ProtocolBuffers

https://rsbh.dev/blogs/grpc-with-nodejs-typescript