dependency-injectionnestjs

Why is my Nestjs Service being instantiated twice?


I have the following NgrokService here:

@Injectable()
export class NgrokService
  implements OnApplicationBootstrap, OnApplicationShutdown
{
  port: string
  ngrokToken: string
  ngrok: typeof import('ngrok') | null = null

  constructor(private readonly configService: ConfigService) {
    this.port = this.configService.get('API_PORT') ?? '3001'

    this.ngrokToken = this.configService.getOrThrow('NGROK_TOKEN')

    if (process.env.NODE_ENV === 'development') this.ngrok = require('ngrok')
  }

  async onApplicationBootstrap() {
    if (process.env.NODE_ENV !== 'development') {
      return
    }

    this.tunnelUrl = await this.ngrok!.connect({
      addr: `https://localhost:${this.port}`,
      subdomain: '<my_subdomain>',

      region: 'us',
      authtoken: this.ngrokToken,
    })
  }

  async onApplicationShutdown() {
    if (process.env.NODE_ENV !== 'development') {
      return
    }

    this.ngrok!.disconnect()
  }
}

I'm using it here:

@Module({
  imports: [],
  controllers: [HealthController],
  providers: [HealthService, AwsService, NgrokService],
})
export class HealthModule {}

and also here:

@Module({
  imports: [
    ...
  ],
  controllers: [...],
  providers: [
    ...
    NgrokService
  ],
})
export class AppModule {}

For some reason though, the onApplicationBootstrap hook gets called twice. After digging, I was only able to solve it by wrapping the service in a module and creating a global lock variable that checks if the connection was already made.

I just want to understand why this is happening. Why is Nestjs instantiating the service twice? Even wrapped in a module, the service gets instantiated twice.


Solution

  • providers are singleton by default per module

    so if you have NgrokService registered (ie, in the providers array) in multiple modules, you'll get multiple instances.