NestJSIntermediate

How NestJS Dependency Injection Works

Master DI patterns in 5 minutes with interactive examples

⏱️ 5 min readπŸ’‘ Intermediate

🎯 What You'll Learn:

  • How NestJS DI container works internally
  • 3 types of injection patterns
  • Common DI pitfalls and how to avoid them
  • Production-ready best practices

NestJS Dependency Injection Flow

How the magic happens ✨

1
Module declares providers
@Module({ providers: [UserService] })
2
NestJS scans for @Injectable
Finds decorated classes
3
Container creates instances
Automatic instantiation
Interactive Flow Diagram

🧠 Understanding the Concept

Dependency Injection (DI) is a design pattern where dependencies are provided to a class rather than the class creating them. In NestJS, the IoC (Inversion of Control) container automatically manages this for you.

Why use DI?

  • Testability: Mock dependencies easily in tests
  • Loose Coupling: Change implementations without breaking code
  • Scalability: Share instances across application (singleton pattern)
  • Maintainability: Clear dependency graph

πŸ’» Code Example: Basic DI

user.service.ts
1import { Injectable } from '@nestjs/common';
2
3@Injectable()
4export class UserService {
5  private users = [];
6
7  findAll() {
8    return this.users;
9  }
10
11  create(user: any) {
12    this.users.push(user);
13    return user;
14  }
15}
user.controller.ts
1import { Controller, Get } from '@nestjs/common';
2import { UserService } from './user.service';
3
4@Controller('users')
5export class UserController {
6  // Constructor injection
7  constructor(private readonly userService: UserService) {}
8
9  @Get()
10  findAll() {
11    return this.userService.findAll();
12  }
13}
user.module.ts
1import { Module } from '@nestjs/common';
2import { UserController } from './user.controller';
3import { UserService } from './user.service';
4
5@Module({
6  providers: [UserService],
7  controllers: [UserController],
8  exports: [UserService], // Export if other modules need it
9})
10export class UserModule {}

πŸš€ Production Pattern: Custom Providers

useFactory pattern for dynamic providers
1import { Module } from '@nestjs/common';
2import { ConfigService } from '@nestjs/config';
3
4@Module({
5  providers: [
6    {
7      provide: 'DATABASE_CONNECTION',
8      useFactory: (configService: ConfigService) => {
9        const host = configService.get('DB_HOST');
10        const port = configService.get('DB_PORT');
11        return createConnection({ host, port });
12      },
13      inject: [ConfigService],
14    },
15  ],
16})
17export class DatabaseModule {}

When to use useFactory?

  • Configuration-based initialization
  • Async initialization
  • Third-party library integration
  • Different instances per request (REQUEST scope)

⚠️ Common Pitfalls

1. Circular Dependencies

When Service A depends on Service B, and Service B depends on Service A.

solution.ts
1import { forwardRef, Inject } from '@nestjs/common';
2
3constructor(@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB) {}

2. Forgetting @Injectable()

Every provider must have the @Injectable() decorator.

3. Missing Provider Registration

Provider must be in module's providers array or imported from another module.

βœ… Key Takeaways

  • βœ“DI makes code testable, maintainable, and scalable
  • βœ“Use @Injectable() decorator on all provider classes
  • βœ“Register providers in @Module() decorator
  • βœ“Inject via constructor parameters for cleaner code
  • βœ“Use custom providers with useFactory for dynamic scenarios
  • βœ“Avoid circular dependencies with forwardRef()

🎯 Interactive Challenge: Arrange the DI Flow

Drag and drop the steps below to arrange them in the correct order of NestJS Dependency Injection flow

Attempts: 0

How to play:

  • β€’ Drag and drop the steps to arrange them in the correct order
  • β€’ The flow should represent the logical sequence of events
  • β€’ Click β€œCheck Order” when you think you've got it right
  • β€’ Get feedback and hints if needed
  • 1
    🎯
    Controller requests service
    constructor(private service: UserService)
  • 2
    βœ…
    NestJS injects instance
    Automatic dependency resolution
  • 3
    πŸ”
    NestJS scans @Injectable
    Finds decorated classes
  • 4
    πŸ“¦
    Module declares providers
    @Module({ providers: [UserService] })
Interactive Flow Diagram

πŸ’‘ Learn by Doing: Implement DI

Practice implementing Dependency Injection in NestJS. Complete the challenge below!

Your Challenge:

Create a PostService and inject it into a PostController using constructor injection. The PostService should have a findAll() method that returns an array of posts.

Interactive Editor
Attempts: 0

πŸ“‡ Memorize Key Concepts

Master NestJS DI through multiple learning modes. Choose your preferred learning style below!

Flashcards: Click to flip cards and review concepts. Self-assess your knowledge with β€œI Know This” or β€œNeed Review” buttons.

πŸ“‡ Flashcards

Test your knowledge with these flashcards

Progress: 0/10 cards reviewedMastery: 0%
Known: 0Review: 0
Card 1 of 10Core Concepteasy

Question

What is Dependency Injection?

Click to reveal answer

πŸ§ͺ Test Your Knowledge

Question 1 of 2Score: 0/2

What is the main benefit of Dependency Injection?

Download PDF Version

Get this guide as a PDF + receive daily backend tips

No spam. Unsubscribe anytime. We respect your privacy.

Daily tips
100% secure
Free forever

πŸ“š Related Posts

Want more NestJS content?

Subscribe to get weekly tutorials and best practices

Subscribe to DailyNest