Under The Hood
backend nestjs NestJS 10+

Circular Dependencies: forwardRef() and Module Dependency Cycles

Last updated
Prerequisites:
NestJS Dependency Injection Container
JavaScript ES Module loading order
  • nestjs
  • circular-dependency
  • forwardRef
  • dependency-injection
  • architecture

Read at your depth

The practical view

Circular dependencies occur when Service A injects Service B, and Service B injects Service A (or Module A imports Module B, which imports Module A). At runtime, one service receives `undefined` because JavaScript cannot resolve the circular import. NestJS solves this using `forwardRef(() => TargetClass)` on both the module import and the constructor `@Inject(forwardRef(() => TargetService))`.

The same idea in other frameworks

nestjs equivalent
`@Inject(forwardRef(() => UsersService)) private usersService: UsersService`.

Legacy vs modern

Circular Import Crash vs Resolved forwardRef() Injection

Circular injection causes `TypeError: Cannot read properties of undefined`; `forwardRef()` defers reference resolution.

before → after
Circular Dependency Crash
constructor(private usersService: UsersService) {} // ❌ Receives undefined at runtime
Resolved with forwardRef()
constructor(@Inject(forwardRef(() => UsersService)) private usersService: UsersService) {} // ✅ NEW

Interview gotchas

Context

Interviewers test your practical debugging experience with circular dependency resolution.

The mechanical answer

You must use `forwardRef()` on **both the Module imports and the Service constructors**. In `UsersModule`, use `imports: [forwardRef(() => OrdersModule)]`. In `OrdersModule`, use `imports: [forwardRef(() => UsersModule)]`. Additionally, in the service constructor parameters, you must add `@Inject(forwardRef(() => ServiceName))` on both sides.

Trap

Adding `forwardRef` only to the services while forgetting the module `imports` array will still cause module compilation crashes.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.