developing-scalable-microservices-with-nestjs-and-mongodb.html

Developing Scalable Microservices with NestJS and MongoDB

In today's fast-paced digital landscape, scalability and efficiency are paramount for modern applications. The microservices architecture has gained immense popularity as it allows developers to build applications as a suite of independent services. NestJS, a progressive Node.js framework, combined with MongoDB, a NoSQL database, provides a robust foundation for developing scalable microservices. In this article, we will explore the core concepts of microservices, delve into the features of NestJS, and demonstrate how to integrate MongoDB effectively.

What are Microservices?

Microservices are an architectural style that structures an application as a collection of loosely coupled services. Each service is responsible for a specific business capability, allowing teams to develop, deploy, and scale them independently. This approach offers several advantages:

  • Scalability: Each service can be scaled independently based on demand.
  • Flexibility: Different services can be developed using different technologies.
  • Resilience: Failure in one service does not necessarily affect the others.
  • Faster development: Teams can work on different services concurrently.

Why Choose NestJS?

NestJS is built on top of Express and leverages TypeScript, making it an excellent choice for building scalable and maintainable server-side applications. Here are a few compelling reasons to use NestJS for microservices:

  • Modular Architecture: NestJS encourages a modular approach, which aligns perfectly with microservices.
  • Dependency Injection: Built-in dependency injection makes it easy to manage service dependencies.
  • Interceptors and Guards: NestJS provides powerful tools to handle requests and apply business logic.
  • Microservices Support: NestJS has built-in support for microservices, allowing you to choose the transport layer (e.g., HTTP, MQTT, gRPC).

Setting Up Your Development Environment

Before we dive into coding, let’s set up our environment. You will need:

  • Node.js: Ensure you have Node.js installed (preferably LTS version).
  • Nest CLI: Install the Nest CLI globally using the command: bash npm install -g @nestjs/cli
  • MongoDB: You can either install MongoDB locally or use a cloud service like MongoDB Atlas.

Creating a New NestJS Project

Start by creating a new NestJS project:

nest new microservice-demo
cd microservice-demo

Next, install the necessary packages for MongoDB:

npm install @nestjs/mongoose mongoose

Structuring Your Microservice

Step 1: Setting Up Mongoose with NestJS

Create a new module for your microservice:

nest generate module cats
nest generate service cats
nest generate controller cats

In your cats.module.ts, import Mongoose and define your schema:

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';
import { Cat, CatSchema } from './schemas/cat.schema';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }]),
  ],
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

Step 2: Defining the Cat Schema

Create a new file cat.schema.ts in the schemas directory:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type CatDocument = Cat & Document;

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

  @Prop()
  age: number;

  @Prop()
  breed: string;
}

export const CatSchema = SchemaFactory.createForClass(Cat);

Step 3: Implementing the Cats Service

In cats.service.ts, implement the methods to handle CRUD operations:

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Cat, CatDocument } from './schemas/cat.schema';

@Injectable()
export class CatsService {
  constructor(@InjectModel(Cat.name) private catModel: Model<CatDocument>) {}

  async create(cat: Cat): Promise<Cat> {
    const newCat = new this.catModel(cat);
    return newCat.save();
  }

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

  async findOne(id: string): Promise<Cat> {
    return this.catModel.findById(id).exec();
  }

  async update(id: string, cat: Cat): Promise<Cat> {
    return this.catModel.findByIdAndUpdate(id, cat, { new: true }).exec();
  }

  async delete(id: string): Promise<Cat> {
    return this.catModel.findByIdAndRemove(id).exec();
  }
}

Step 4: Creating the Cats Controller

In cats.controller.ts, define the endpoints:

import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './schemas/cat.schema';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Post()
  create(@Body() cat: Cat) {
    return this.catsService.create(cat);
  }

  @Get()
  findAll() {
    return this.catsService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.catsService.findOne(id);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() cat: Cat) {
    return this.catsService.update(id, cat);
  }

  @Delete(':id')
  delete(@Param('id') id: string) {
    return this.catsService.delete(id);
  }
}

Step 5: Connecting to MongoDB

In your main.ts, set up the connection to MongoDB:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MongooseModule } from '@nestjs/mongoose';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await MongooseModule.forRoot('mongodb://localhost/nest'); // Replace with your MongoDB URI
  await app.listen(3000);
}
bootstrap();

Conclusion

In this article, we’ve walked through the essential steps to develop scalable microservices using NestJS and MongoDB. By leveraging the modular architecture of NestJS and the flexibility of MongoDB, you can create robust applications that are easy to maintain and scale.

Key Takeaways:

  • Modularity: Use NestJS’s modular architecture to build microservices.
  • Dependency Injection: Take advantage of dependency injection for better code management.
  • CRUD Operations: Implement CRUD operations effectively using Mongoose.

As you continue your journey in microservices development, explore advanced topics such as message brokers, service discovery, and containerization to further enhance your applications. Happy coding!

SR
Syed
Rizwan

About the Author

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