TechLog
Backend
Nestjs
Microservice Dynamic Bootstrap

Dynamically Configuring Microservice Bootstrap

During setting up microservice in nestjs, I faced a challenge. By convention, and as illustrated in nestjs documentation, microservice is boostrapped using following convention.

main.ts
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
 
async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      transport: Transport.TCP,
      options: {
        url: 'xxx.url.com',
        protoPackage: 'some/hard/coded/path',
      }
    },
  );
  await app.listen();
}
bootstrap();

The above configuration, however, is static. Therefore, it includes hard coding, such as the port/url, transport method, etc.

I wanted to make the microservice configuration using .env variables, using ConfigService offered by @nestjs/config.

Therefore, I had to find a way to somehow import config module within the provided code, but it was difficult. From my research, I found an nestjs open discussion that illustrates the problem (link (opens in a new tab)).

I then decided to define an ApplicationConetext, and use configService that gets the ConfigService provider in my AppModule. From the configSerivce, I defined my microserviceOptions. With these, I then created the actual app, and closed the temporary appContext. Note that inorder to achieve this, my AppModule must import ConfigModule.

main.ts
async function bootstrap() {
  const appContext = await NestFactory.createApplicationContext(AppModule);
  const configService = appContext.get(ConfigService);
  const url = configService.get<string>('MICROSERVICE_APP_URL');
 
  const microserviceOptions: MicroserviceOptions = {
    transport: Transport.GRPC,
    options: {
      url,
      protoPath: join(__dirname, '../app.proto'),
      package: APP_PACKAGE_NAME,
    },
  };
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AuthModule,
    microserviceOptions,
  );
  appContext.close();
  await app.listen();
}
bootstrap();