DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • How To Implement and Design Twitter Search Backend Systems using Java Microservices?
  • Scaling Salesforce Apps Using Heroku Microservices - Part 2
  • What Does Synchronization With Asyncio Look Like
  • Data Management Patterns for Microservices

Trending

  • Architecting Autonomous Agents: A Deep Dive into Azure AI Foundry Agent Service
  • Security Readiness Checklist: From AI Threats to Software Supply Chain Defense
  • How AI Is Rewriting the Rules of Software Security: Machine-Speed Delivery, Shifting Risk, and New Control Points
  • Spring CRUD Generator v1.1.0 Updates
  1. DZone
  2. Data Engineering
  3. Data
  4. Create a Multi-tenancy Application In Nest.js - Part 1

Create a Multi-tenancy Application In Nest.js - Part 1

In this article, we are going to work on an example about the multi-tenant application mode using multiple databases and microservices architecture.

By 
Ismaeil Shajar user avatar
Ismaeil Shajar
·
Nov. 16, 21 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
16.7K Views

Join the DZone community and get the full member experience.

Join For Free

Overview

Multitenancy is an operational mode in SaaS applications where various independent instances are allocated to the same environment. To put it simply, multitenancy is having multiple tenants (businesses) use the same Saas application.

Multitenancy Archituecture

This article will not discuss designing a multitenancy application, however, you can read about it in detail here: What is Multi-Tenant Architecture? From here on, we are going to work on an example about the multi-tenants using multiple databases and microservices architecture.

What Are We Going To Build?

We will focus on ROLE-BASED ACCESS CONTROL with multi-database and will use two databases -MySQL and MongoDB- for each tenant:  We will use sample web services to test the flow, for example creating users, sending and receiving notifications, etc.

Nest.js

From nest js: nest (NestJS) is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with and fully supports TypeScript (yet still enables developers to code in pure JavaScript), and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).

Installation

Firstly, You need to install Node.js if you don't have it already and make sure it's version 10.13 or higher. I will install v12 LTS and npm. I recommend that you use nvm to install node.js

Setup

You need to install nest CLI using npm:

npm install -g @nestjs/cli


Then create a new nest.js project:

nest new multi_tenant 


If you run into an error during the installation like:

npm ERR! invalid json response body at https://registry.npmjs.org/ajv reason: Unexpected end of JSON input.

You can use this to fix it:

npm cache clean --force


Microservices Setup

Although we can create a monolithic application, it is not usually the cause for mulit-tenancy applications, since they can be quite big, the better and harder approach is to use microservices.

Let's start the microservices architecture setup, first install dependency:

npm i --save @nestjs/microservices


We will use Redis as a transport layer so install Redis client using npm:

npm i --save Redis


We also need to install Redis server, I will use docker to install the Redis server:

docker run --name my-redis-container -p 6379:6379 -d redis


Now we need to test the application setup before we create another microservice.

Edit the following:

main.ts

In src/main.ts replace the bootstrap method by:

const app = await NestFactory.create(AppModule);
 app.connectMicroservice<MicroserviceOptions>({
   transport:Transport.REDIS,
   options:{
     url:'redis://127.0.0.1:6379'
   },
 });

 await app.startAllMicroservices();
 await app.listen(3000);


Creating Microservices in an Application

We will start with two applications: notifications and user services. Using generate app command in nest CLI:

nest g app user-service
nest g app notification


Now the application directory will look like this: 

The new service will be created like a new project but will share the same project.json file. We need to change all services' main.ts to work with Redis and change their ports to be unique.

Go to /apps/user-service/src/main.ts and /apps/notification/src/main.ts and add Redis connection and microservice starter>

const app = await NestFactory.create(NotificationModule);
 
 // new connection
 app.connectMicroservice<MicroserviceOptions>({
    transport:Transport.REDIS,
    options:{
      url:'redis://127.0.0.1:6379'
    },
  });
 await app.startAllMicroservices();
 /// the rest
   await app.listen(<port>); // any service must have diffrent port or no port if not use http service and client 


Before we start editing we need to start the services in dev mode using the following command:

npm run start:dev 
npm run start:dev notification 


Currently, there is no need to start the user-service.

Edit Configuration and Controller

To send data between services; first, we will start with the needed configuration and controller. To make it simple, we will send two integers to the notification service and return the user name and the summation of the two integers.

In the main service app.module, we need to add a client to send data to the notification.

But what does app.module.ts do? The @Module() decorator provides metadata that Nest makes use of to organize the application structure. For more details, you can visit Nest.js @Module()

Edit the module file to add microservices ClientsModule and configure it.

@Module will look like this:

@Module({
  imports: [ClientsModule.register([
    {
      name: 'NOTIFY_SERVICE',
      transport: Transport.REDIS,
      options: {
        url: 'redis://localhost:6379',
      },
    },
  ])],
  controllers: [AppController],
  providers: [AppService],
})


ClientsModule is a type of module called a dynamic module. This feature enables you to easily create customizable modules that can register and configure providers dynamically and you can read about it here

Now, in the app.service we will add a constructer to inject the transport client and edit the getHello method to send the data:

app.service.ts

constructor(
      @Inject('NOTIFY_SERVICE') private readonly client: ClientProxy){}
 async getHello(): Promise<string> { // need to use async because we need to wait recieved data

    let recieve= await this.client.send<number>("notify",{user:"Ali",data:{a:1,b:2}}).toPromise();// notify if mapped key will used to in other hand 
     // without toPromise function will return Observable and will not see execute before subscribe so when convert to Promise will recieve data in variable 
  
    return "\t add 1+2="+recieve;
  }


The transporters support two methods: send() (for request-response messaging) and emit() (for event-driven messaging)

Then in the notification service, we will just use it to receive a request and send a response.

In notification.controller.ts.

Add a new controller (let's call it notify) and use the annotation @MessagePattern with a mapped key notify the same key used in send() function.

@MessagePattern('notify')
  async notify(data:NotifiyData){
    console.log('send')
    Logger.log("notificatoin data"+data.user);
    let a:number=data.data['a'];
    let b:number=data.data['b'];
    console.log(a,b)
    return a+b;
  }


We will add an interface in the same class file to map the received data to an object type:

interface NotifiyData{
  user: string;
  data: object;
}


Run - Now run the main and notification services using:

npm run start:dev 
npm run start:dev notification 


Go to the browser and open the main service URL http://localhost:3000/. The output will be add 1+2=3

You can find the source code available in the Git branch microservices setup.

That's all for today! I'll see you with part 2.

Application directory microservice Web Service Database Redis (company) Role-based access control NEST (software) Data (computing) Npm (software) Notification service

Opinions expressed by DZone contributors are their own.

Related

  • How To Implement and Design Twitter Search Backend Systems using Java Microservices?
  • Scaling Salesforce Apps Using Heroku Microservices - Part 2
  • What Does Synchronization With Asyncio Look Like
  • Data Management Patterns for Microservices

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook