Mermaid dependency graphs: visualize software architecture and component dependencies
Understanding how your components depend on each other is critical for maintainability, refactoring, and system design. Dependency graphs—directed diagrams showing which modules, services, or libraries depend on which—help teams visualize the connections that often stay hidden in code. Mermaid makes it easy to create clear, version-controllable dependency graphs using its graph syntax.
Why dependency visualization matters
Dependencies shape your codebase's architecture. Without a clear picture, you risk:
- Circular dependencies that make refactoring impossible
- Tight coupling between distant modules, increasing fragility
- Hidden transitive dependencies that break when an indirect upstream module changes
- Unclear separation of concerns when layers blur together
- Painful onboarding when new team members can't see the big picture
Dependency graphs turn complexity into clarity, surfacing the architectural decisions you've made (or accidentally inherited).
Dependency graph syntax in Mermaid
Mermaid's graph syntax is ideal for dependencies: nodes are modules or services, and edges show "depends on" relationships.
graph TD
A["Frontend App<br/>React + TypeScript"]
B["API Client<br/>Axios + Redux"]
C["REST API<br/>Node.js + Express"]
D["Database<br/>PostgreSQL"]
E["Cache<br/>Redis"]
F["Auth Service<br/>JWT + Passport"]
A --> B
B --> C
C --> D
C --> E
C --> F
B --> F
Each arrow points "downward" to a dependency: "A depends on B" means A cannot function without B. This creates a dependency tree where leaf nodes (with no outgoing edges) have no dependencies themselves.
Real-world example: microservices architecture
Here's a typical e-commerce system with multiple services:
graph TD
Client["🌐 Web Client<br/>React + Redux"]
Mobile["📱 Mobile App<br/>React Native"]
Gateway["API Gateway<br/>Kong"]
Auth["🔐 Auth Service<br/>OAuth 2.0"]
User["👤 User Service<br/>Microservice"]
Product["🛍️ Product Service<br/>Microservice"]
Order["📦 Order Service<br/>Microservice"]
Payment["💳 Payment Service<br/>Microservice"]
Notification["🔔 Notification Service<br/>Queue + Workers"]
UserDB["User DB<br/>PostgreSQL"]
ProductDB["Product DB<br/>PostgreSQL"]
OrderDB["Order DB<br/>PostgreSQL"]
Cache["Cache Layer<br/>Redis"]
Queue["Message Queue<br/>RabbitMQ"]
Client --> Gateway
Mobile --> Gateway
Gateway --> Auth
Gateway --> User
Gateway --> Product
Gateway --> Order
Gateway --> Payment
User --> UserDB
User --> Cache
Product --> ProductDB
Product --> Cache
Order --> OrderDB
Order --> Cache
Order --> Queue
Payment --> Queue
Auth --> UserDB
Queue --> Notification
Notification --> Cache
This diagram shows:
- Two client types depend on the API Gateway
- Gateway routes to five services (auth, user, product, order, payment)
- Each service owns its database (database-per-service pattern)
- Shared cache layer for performance
- Message queue for async operations
- Notification service consumes from the queue
Advanced: highlighting dependency layers
For larger systems, color-code dependencies by layer to show architectural tiers:
graph TD
subgraph Presentation["🖥️ Presentation Layer"]
Web["Web UI"]
Mobile["Mobile App"]
end
subgraph API["🔌 API Layer"]
Gateway["API Gateway"]
end
subgraph Business["💼 Business Logic"]
Auth["Auth Service"]
Order["Order Service"]
Inventory["Inventory Service"]
end
subgraph Data["🗄️ Data Layer"]
AuthDB["Auth DB"]
OrderDB["Order DB"]
InventoryDB["Inventory DB"]
Cache["Cache"]
end
subgraph External["🌍 External"]
PaymentGW["Payment Gateway"]
Email["Email Service"]
end
Web --> Gateway
Mobile --> Gateway
Gateway --> Auth
Gateway --> Order
Gateway --> Inventory
Auth --> AuthDB
Auth --> Cache
Order --> OrderDB
Order --> Cache
Order --> PaymentGW
Inventory --> InventoryDB
Inventory --> Cache
Order --> Email
Each subgraph represents a tier; arrows cross tiers cleanly. This makes it obvious which layers can talk to which (presentation speaks only to API; API speaks to business; business speaks to data and external services).
Identifying and fixing problematic dependencies
Common dependency issues appear visually:
| Issue | What it looks like | Fix |
|---|---|---|
| Circular dependency | A → B → A (a loop) | Introduce an abstraction layer or message queue |
| Tight coupling | A → B and A → C and B → C (many arrows) | Extract shared logic into a library; use interfaces |
| Implicit transitive dep | A → B → D, but A also uses D directly | Make the dependency explicit (A → D) or use B's API only |
| Layer violation | Presentation layer connects directly to Data layer | Route through API/Business layer |
| God service | One service connects to everything | Split into smaller, focused services; use facade pattern |
For example, a cycle (Auth → User → Auth) indicates design confusion. Resolve by:
- Moving shared logic to a third module
- Having both depend on that module instead of each other
- Using callbacks or events to break the cycle
Frontend dependencies: libraries and modules
Dependency graphs also work great for frontend architecture:
graph TD
App["App Component<br/>Root"]
Store["Redux Store"]
UI["UI Component Library<br/>Shadcn"]
Form["Form Handling<br/>React Hook Form"]
Fetch["Data Fetching<br/>TanStack Query"]
Pages["Page Components<br/>Dashboard, Settings"]
App --> Store
App --> Pages
App --> UI
Pages --> Form
Pages --> Fetch
Form --> UI
Fetch --> Store
Fetch --> UI
This shows:
- App is the root, depends on Store, Pages, and UI
- Pages depend on Form, Fetch, and (indirectly) UI
- Form and Fetch both depend on UI and Store
- Store is a hub; many modules depend on it
Best practices for dependency graphs
- One direction only — Agree on whether edges point from dependant to dependency (A → B means "A depends on B") or vice versa. Mermaid doesn't enforce direction, so be consistent.
- Group related dependencies — Use subgraphs to cluster services by tier, team, or domain.
- Avoid too many edges — If your graph is a dense hairball, your architecture is too coupled. Refactor first, then draw.
- Label edges for complex relationships — Use edge labels to clarify "depends on," "calls," "publishes to," etc.
- Keep it updated — Dependency graphs rot. Make updating it part of your code review process (e.g., "If you add a new service dependency, update the diagram").
- Use in documentation — Commit your dependency graph in your repo's README or architecture docs; version it like code.
Comparing dependency graphs to other diagrams
| When | What to use |
|---|---|
| Showing which services depend on which | Dependency graph (this post) |
| Showing how data flows at runtime | Sankey diagram or sequence diagram |
| Showing the build pipeline | Flowchart or CI/CD pipeline |
| Showing request/response over time | Sequence diagram |
| Showing system layers | Block diagram or dependency graph with subgraphs |
FAQ
How do I detect cycles in my dependencies?
Look for closed loops in your diagram (A → B → C → A). If you see any, your architecture has a cycle—trace the path in code and refactor to break it. Consider using automated tools like npm-check-circular for Node.js or pydepend for Python.
Should I include all dependencies or just direct ones?
Start with direct dependencies only; your diagram stays readable. If you need transitive dependencies (A → B → D), you can add them with different arrow styles (dashed vs. solid).
Can I auto-generate dependency graphs from code?
Yes. Tools like ts-graph (TypeScript), pydepend (Python), and depcheck (JavaScript) analyze your code and export dependency data. You can convert that to Mermaid format programmatically—great for keeping diagrams in sync with reality.
What's the difference between a dependency graph and an UML class diagram?
A UML class diagram shows relationships between classes (inheritance, composition, association). A dependency graph shows relationships between modules or services (which one depends on the other at runtime). They work at different levels of abstraction.
Map your architecture with dependency graphs in the MermaidCreator editor. Clear dependencies lead to modular, maintainable systems that teams can reason about.
Related posts
Mermaid packet diagrams: visualize network topology and data flows
Document network architectures and packet routing with Mermaid packet diagrams. Learn syntax, real-world examples, and when to use for infrastructure visualization.
Mermaid sequence diagram actors and lifelines: messaging patterns
Master sequence diagram fundamentals — design interactions between services, APIs, and users with proper actor notation, lifelines, and message ordering.