how-to-build-scalable-microservices-with-nestjs-and-mongodb.html

How to Build Scalable Microservices with NestJS and MongoDB

In today’s rapidly evolving tech landscape, building scalable applications that can handle increased loads without compromising performance is paramount. Microservices architecture has emerged as a powerful design pattern, allowing developers to create modular and independent services that can be deployed and scaled individually. When paired with powerful frameworks like NestJS and databases like MongoDB, building these services becomes not only efficient but also enjoyable. In this article, we’ll explore how to build scalable microservices using NestJS and MongoDB, walking through definitions, use cases, and actionable insights, complete with code examples.

What Are Microservices?

Microservices are an architectural style that structures an application as a collection of small, independently deployable services. Each service is designed to perform a specific business function and can be developed, deployed, and scaled independently of other services. This modularity helps to enhance maintainability and scalability.

Key Characteristics of Microservices:

  • Independent Deployment: Each service can be deployed without affecting other services.
  • Decentralized Data Management: Each service can manage its own database, making it easier to handle data storage and retrieval.
  • Technology Agnostic: Different services can be built using different technologies, allowing teams to choose the best tools for the job.
  • Resilience: Failures in one service do not necessarily bring down the entire application.

Why Use NestJS and MongoDB?

NestJS

NestJS is a progressive Node.js framework designed for building efficient, reliable, and scalable server-side applications. It leverages TypeScript and incorporates decorators and dependency injection, making it ideal for developing microservices.

MongoDB

MongoDB is a NoSQL database that stores data in a flexible, JSON-like format, making it perfect for applications that require scalability and high performance. Its document-based structure aligns well with microservices, allowing each service to have its own database schema.

Setting Up Your Environment

Before diving into code, ensure that you have the following installed:

  • Node.js (version 12 or later)
  • MongoDB (either locally or using MongoDB Atlas)
  • NestJS CLI

Step 1: Install NestJS CLI

First, install the NestJS CLI globally on your machine:

npm i -g @nestjs/cli

Step 2: Create a New Project

Create a new NestJS project:

nest new microservice-example

Navigate to the project directory:

cd microservice-example

Step 3: Install Necessary Packages

You will need to install the MongoDB package and the Mongoose ORM for data modeling:

npm install @nestjs/mongoose mongoose

Creating a Sample Microservice

Now, let’s create a simple microservice that manages a collection of "users."

Step 4: Define the User Schema

Create a new folder called users in the src directory, and inside it, create a file called user.schema.ts.

// src/users/user.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type UserDocument = User & Document;

@Schema()
export class User {
  @Prop({ required: true })
  name: string;

  @Prop({ required: true, unique: true })
  email: string;

  @Prop()
  password: string;
}

export const UserSchema = SchemaFactory.createForClass(User);

Step 5: Create the Users Module

Generate a users module and service:

nest generate module users
nest generate service users

Then, update the users.module.ts to include Mongoose and the User schema:

// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { UsersService } from './users.service';
import { User, UserSchema } from './user.schema';

@Module({
  imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

Step 6: Implementing the Users Service

Now, let’s implement the logic to create and retrieve users in users.service.ts:

// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, UserDocument } from './user.schema';

@Injectable()
export class UsersService {
  constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}

  async create(createUserDto: { name: string; email: string; password: string }): Promise<User> {
    const createdUser = new this.userModel(createUserDto);
    return createdUser.save();
  }

  async findAll(): Promise<User[]> {
    return this.userModel.find().exec();
  }
}

Step 7: Setting Up the Controller

Now we need to add a controller to handle incoming requests. Generate a users controller:

nest generate controller users

In users.controller.ts, implement the endpoints:

// src/users/users.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  async create(@Body() createUserDto: { name: string; email: string; password: string }) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  async findAll() {
    return this.usersService.findAll();
  }
}

Step 8: Connecting to MongoDB

In your main.ts, connect to your MongoDB database:

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Mongoose } from 'mongoose';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Connect to MongoDB
  await Mongoose.connect('mongodb://localhost/nest', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  });

  await app.listen(3000);
}
bootstrap();

Conclusion

By following these steps, you have successfully set up a scalable microservice using NestJS and MongoDB. This architecture allows your application to grow seamlessly, as you can add new services or scale existing ones without major overhauls.

Additional Tips for Scalability:

  • Load Balancing: Use a load balancer to distribute traffic among multiple instances of your microservices.
  • Caching: Implement caching strategies (like Redis) to reduce database load.
  • Service Discovery: Use tools like Consul or Eureka to manage service discovery in a microservices environment.

Building microservices with NestJS and MongoDB not only enhances scalability but also fosters a robust development environment that can adapt to changing business needs. Start coding today and watch your application thrive!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.