Building Scalable Microservices with TypeScript and NestJS: A Step-by-Step Guide
Learn how to build scalable microservices using TypeScript and NestJS with practical, beginner-friendly steps.
Microservices architecture allows developers to build scalable and maintainable applications by breaking down a complex system into smaller, independent services. In this guide, you will learn how to create scalable microservices using TypeScript and NestJS, a progressive Node.js framework that makes building efficient and reliable server-side applications easier.
First, make sure you have Node.js and npm installed on your machine. Then, install the NestJS CLI globally using the following command:
npm install -g @nestjs/cliNow, create a new NestJS project for your microservice:
nest new user-serviceNavigate into your project directory:
cd user-serviceNestJS supports various transport layers for microservices communication. For this beginner tutorial, we will use TCP transport, which is simple and effective for internal communication between microservices.
Let's set up the main microservice server. Open `src/main.ts` and update it as follows:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
transport: Transport.TCP,
options: {
host: '127.0.0.1',
port: 3001,
},
});
await app.listen();
console.log('User microservice is listening on port 3001');
}
bootstrap();Next, create a simple service that listens to messages and responds. Modify `src/app.service.ts` to handle a request pattern called 'get_user':
import { Injectable } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
@Injectable()
export class AppService {
// Simulate user data
private users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
@MessagePattern({ cmd: 'get_user' })
getUser(data: { id: number }) {
const user = this.users.find(user => user.id === data.id);
return user || { error: 'User not found' };
}
}We also need to register the service in the module file. Confirm your `src/app.module.ts` contains the following:
import { Module } from '@nestjs/common';
import { AppService } from './app.service';
@Module({
providers: [AppService],
})
export class AppModule {}Now, we will create a separate client service that communicates with this user microservice. Create a new directory outside of your current project, for example `client-service`, and initialize another NestJS app:
nest new client-service
cd client-serviceInstall the microservices package if not included:
npm install --save @nestjs/microservicesIn your client service, set up a client proxy to communicate with the user microservice. Modify `src/app.service.ts` like this:
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices';
@Injectable()
export class AppService implements OnModuleInit {
private client: ClientProxy;
onModuleInit() {
this.client = ClientProxyFactory.create({
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 3001 },
});
}
async getUser(id: number) {
return this.client.send({ cmd: 'get_user' }, { id }).toPromise();
}
}In a controller, you can now invoke this service method to fetch user data:
import { Controller, Get, Param } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('users')
export class AppController {
constructor(private readonly appService: AppService) {}
@Get(':id')
async getUser(@Param('id') id: string) {
const userId = parseInt(id, 10);
return await this.appService.getUser(userId);
}
}Finally, start your user microservice by running `npm run start` inside `user-service` directory, and start the client service by running `npm run start` inside the `client-service` directory. Your client will now forward user-related HTTP requests to the user microservice using TCP.
This simple example shows how NestJS and TypeScript allow you to build microservices that communicate efficiently. You can expand this architecture by adding more microservices, using message brokers like RabbitMQ or Kafka, and applying advanced patterns such as service discovery and distributed tracing for better scalability.
With this foundation, you’re ready to explore building real-world scalable microservices using NestJS.