Suggest an editImprove this articleRefine the answer for “Circular dependency between modules”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A circular dependency happens when two (or more) modules or providers depend on each other directly or through a chain; Nest can't build the dependency graph and throws `A circular dependency has been detected between modules`, so the application won't start. **Key point:** it's solved with `forwardRef()` - for modules via `imports: [forwardRef(() => OtherModule)]`, for services via `@Inject(forwardRef(() => OtherService))`; but it's better to rethink the architecture and move the shared logic into a separate `SharedModule`.Shown above the full answer for quick recall.Answer (EN)Image## What a circular dependency is A **circular dependency** happens when **two (or more) modules or providers depend on each other, directly or through a chain**. For example: ```javascript AuthModule → UsersModule → AuthModule ``` or ```javascript AuthService → UsersService → AuthService ``` ## An example of the problem with modules ```javascript // auth.module.ts @Module({ imports: [UsersModule], // AuthModule depends on UsersModule providers: [AuthService], }) export class AuthModule {} ``` ```javascript // users.module.ts @Module({ imports: [AuthModule], // UsersModule depends on AuthModule providers: [UsersService], }) export class UsersModule {} ``` On startup: ```javascript Error: Nest cannot create the module instance. A circular dependency has been detected between modules. ``` NestJS can't build the dependency graph, because each module is waiting for the other to be created. ## Why this happens Nest builds a **Dependency Graph**: - When `AuthModule` imports `UsersModule`, Nest first has to create `UsersModule`. - But `UsersModule`, in turn, imports `AuthModule`, and the process loops. As a result, NestJS **doesn't know where to start**, and throws an error about the circular dependency. ## The same problem can happen with providers ```javascript @Injectable() export class AuthService { constructor(private readonly usersService: UsersService) {} } @Injectable() export class UsersService { constructor(private readonly authService: AuthService) {} } ``` Here NestJS also gets "stuck" creating the instances: - `AuthService` needs `UsersService`, - but creating `UsersService` needs `AuthService`. ## How to solve the problem NestJS provides a special tool, `forwardRef()`. ### The fix for modules Use `forwardRef()` when importing the dependent module: ```javascript // auth.module.ts @Module({ imports: [forwardRef(() => UsersModule)], // the key change providers: [AuthService], exports: [AuthService], }) export class AuthModule {} ``` ```javascript // users.module.ts @Module({ imports: [forwardRef(() => AuthModule)], // the mutual dependency is now allowed providers: [UsersService], exports: [UsersService], }) export class UsersModule {} ``` Now Nest knows these modules **reference each other "lazily"**, and can build the dependency graph correctly. ### The fix for services Also with `forwardRef()`: ```javascript @Injectable() export class AuthService { constructor( @Inject(forwardRef(() => UsersService)) private readonly usersService: UsersService, ) {} } @Injectable() export class UsersService { constructor( @Inject(forwardRef(() => AuthService)) private readonly authService: AuthService, ) {} } ``` `forwardRef()` tells the DI container: > "Don't create this dependency right now, create it once it's actually needed." ## How this works internally - With a normal dependency, Nest creates instances **at initialization time**. - With `forwardRef()`, it registers a **lazy reference**, and fills in the dependency **later**, once all the providers are available. ## Design tips (to avoid cycles) 1. **Split responsibilities**: if two modules depend on each other, the logic was probably split poorly. → Pull the shared part out into a **third module** (e.g. `SharedModule` or `CoreModule`). 2. **Export only what's needed.** Don't export entire modules unnecessarily, just the specific services. 3. **Avoid mutual dependencies between services.** Sometimes a direct reference can be replaced with events, callbacks, or repositories. ## What happens if you don't use `forwardRef()` NestJS: - won't be able to resolve the dependencies; - will throw: ```javascript Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument UsersService at index [0] is available in the AuthModule context. ``` And the application simply won't start. ## Summary | Point | Description | |---|---| | What it is | A situation where two modules or services depend on each other | | Cause | Nest can't determine the order to create the instances in | | Fix | Use `forwardRef(() => TargetModule)` or `@Inject(forwardRef(() => TargetService))` | | Better approach | Rethink the architecture and move the shared logic into a separate module | | If left unfixed | A startup error: "Circular dependency detected" |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.