Episode ini membahas provider sebagai inti dependency injection NestJS: membuat service, menyuntikkannya ke controller, memahami scope singleton dan request-scoped, custom provider, factory provider, alias provider, serta batas dan berbagi provider antar module.

Jika controller adalah gerbang, maka provider adalah mesin di baliknya. Provider berisi logika bisnis aplikasi, dan NestJS mengelola siklus hidupnya melalui dependency injection. Memahami provider adalah kunci untuk menulis aplikasi yang terstruktur dan mudah diuji.
Episode 5 membahas provider dari deklarasi sampai berbagi antar module: service dasar, scope, custom provider, dan batas-batas module.
Provider ditandai dengan dekorator @Injectable. Cara paling umum membuat service adalah lewat Nest CLI:
nest g service usersPerintah ini membuat users.service.ts dan mendaftarkannya di module terkait.
import { Injectable } from "@nestjs/common";
@Injectable()
export class UsersService {
private readonly users: string[] = ["Arman", "Budi"];
findAll(): string[] {
return this.users;
}
}Dekorator @Injectable menandakan class ini bisa disuntikkan ke class lain oleh container DI.
Provider harus didaftarkan di array providers module agar dikenali container:
import { Module } from "@nestjs/common";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}Sekarang service bisa disuntikkan ke controller lewat constructor:
@Controller("users")
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll(): string[] {
return this.usersService.findAll();
}
}Kalian tidak perlu membuat new UsersService() — container yang membuat dan menyuntikkannya. Ini disebut constructor injection.
Secara default, provider bersifat singleton: satu instance dibagikan ke seluruh aplikasi. Untuk kebutuhan per-request, gunakan scope:
import { Injectable, Scope } from "@nestjs/common";
@Injectable({ scope: Scope.REQUEST })
export class RequestLogService {
private readonly requestId: string;
constructor() {
this.requestId = Math.random().toString(36);
}
getRequestId(): string {
return this.requestId;
}
}Dengan Scope.REQUEST, setiap request mendapat instance baru. Ini berguna untuk data per-request seperti request id, tetapi lebih berat secara performa — gunakan hanya jika perlu.
Provider tidak harus berupa class — bisa juga nilai statis:
const CONFIG = {
provide: "APP_NAME",
useValue: "Belajar NestJS",
};Token APP_NAME adalah string yang dipakai sebagai kunci. Untuk mengonsumsi, gunakan @Inject:
import { Inject, Injectable } from "@nestjs/common";
@Injectable()
export class AppService {
constructor(@Inject("APP_NAME") private readonly appName: string) {}
}Untuk nilai yang dibuat dinamis atau bergantung provider lain:
const DB_PROVIDER = {
provide: "DATABASE_URL",
useFactory: (config: ConfigService) => {
return config.get("DATABASE_URL");
},
inject: [ConfigService],
};useFactory menjalankan fungsi saat container menginisialisasi, dan inject menentukan dependensi yang disuntikkan ke fungsi tersebut. Pola ini berguna saat nilai provider perlu dihitung dari konfigurasi atau provider lain.
Provider bersifat privat terhadap module-nya. Untuk memakai provider di module lain, ekspor dulu:
@Module({
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}Module lain yang mengimpor UsersModule kini bisa menyuntikkan UsersService. Pattern ini menjaga boundary: module tidak saling melihat provider internal, hanya yang diekspor.
Episode 5 menjelaskan bagaimana provider menjadi fondasi dependency injection NestJS. Kalian sudah paham deklarasi service, constructor injection, scope, custom provider, dan cara berbagi provider antar module.
Inti yang harus dibawa pulang:
@Injectable dan didaftarkan di array providers.Scope.REQUEST untuk per-request.useValue menyediakan nilai statis; useFactory nilai dinamis.@Inject memakai token string untuk custom provider.Di episode 6 selanjutnya kita akan membahas data access dan persistence — integrasi database dengan TypeORM, Sequelize, atau Prisma, definisi entity dan migrations, repository pattern dan query builder, serta penggunaan database in-memory untuk development dan testing.