Script Valley
Writing Clean Code: Naming, Functions & Structure
Code Structure and OrganizationLesson 3.4

How to avoid circular dependencies between modules

circular dependency definition, dependency direction, dependency inversion, interfaces to break cycles, module dependency graph

Circular Dependencies: What They Are and How to Break Them

Circular dependency diagram

A circular dependency occurs when module A imports from module B, and module B also imports from module A. This creates an import cycle that can cause runtime errors, makes the code impossible to reason about, and breaks tree-shaking.

// user.service.js
import { sendEmail } from './email.service.js';

// email.service.js โ€” creates a cycle!
import { getUserEmail } from './user.service.js';

When Node.js loads this, one module loads before the other is fully initialized, causing hard-to-trace undefined errors.

How to fix circular dependencies:

Option 1 โ€” Extract a shared dependency. If A needs something from B and B needs something from A, the shared logic probably belongs in a third module C that both can import.

// shared/user-utils.js
export function getUserEmail(userId) { ... }

// email.service.js โ€” imports from shared, not user
import { getUserEmail } from '../shared/user-utils.js';

Option 2 โ€” Pass data instead of importing. Instead of email.service importing user.service to get an email, pass the email directly as a parameter.

// email.service.js โ€” no import needed
export function sendWelcomeEmail(toEmail) {
  mailer.send({ to: toEmail, template: 'welcome' });
}

// user.service.js โ€” passes data explicitly
import { sendWelcomeEmail } from './email.service.js';
sendWelcomeEmail(user.email); // no cycle

Dependencies should flow in one direction. Draw your module dependency graph โ€” if any arrows point in a cycle, it's a structural problem that will cost you later.

Up next

How to separate business logic from infrastructure code

Sign in to track progress

How to avoid circular dependencies between modules โ€” Code Structure and Organization โ€” Writing Clean Code: Naming, Functions & Structure โ€” Script Valley โ€” Script Valley