--- title: Avoid Circular Dependencies impact: CRITICAL impactDescription: "#1 cause of runtime crashes" tags: architecture, modules, dependencies --- ## Avoid Circular Dependencies Circular dependencies occur when Module A imports Module B, and Module B imports Module A (directly or transitively). NestJS can sometimes resolve these through forward references, but they indicate architectural problems and should be avoided. This is the #1 cause of runtime crashes in NestJS applications. **Incorrect (circular module imports):** ```typescript // users.module.ts @Module({ imports: [OrdersModule], // Orders needs Users, Users needs Orders = circular providers: [UsersService], exports: [UsersService], }) export class UsersModule {} // orders.module.ts @Module({ imports: [UsersModule], // Circular dependency! providers: [OrdersService], exports: [OrdersService], }) export class OrdersModule {} ``` **Correct (extract shared logic or use events):** ```typescript // Option 1: Extract shared logic to a third module // shared.module.ts @Module({ providers: [SharedService], exports: [SharedService], }) export class SharedModule {} // users.module.ts @Module({ imports: [SharedModule], providers: [UsersService], }) export class UsersModule {} // orders.module.ts @Module({ imports: [SharedModule], providers: [OrdersService], }) export class OrdersModule {} // Option 2: Use events for decoupled communication // users.service.ts @Injectable() export class UsersService { constructor(private eventEmitter: EventEmitter2) {} async createUser(data: CreateUserDto) { const user = await this.userRepo.save(data); this.eventEmitter.emit('user.created', user); return user; } } // orders.service.ts @Injectable() export class OrdersService { @OnEvent('user.created') handleUserCreated(user: User) { // React to user creation without direct dependency } } ``` Reference: [NestJS Circular Dependency](https://docs.nestjs.com/fundamentals/circular-dependency)