If you've ever tried to explain a software system on a whiteboard and wished you could save that diagram as code, mermaid.js solves exactly that problem. Mermaid.js lets you describe architecture diagrams using plain text markup that renders into visual diagrams no drag-and-drop tools needed. For developers, technical writers, and architects who version-control their docs, having mermaid.js architecture diagram markup examples on hand means you can create, update, and share system designs without leaving your workflow.

What is mermaid.js and how does it create architecture diagrams?

Mermaid.js is a JavaScript-based diagramming library that takes text-based markup and renders it into diagrams in the browser. Instead of using a visual editor, you write structured text that describes nodes, connections, and labels. Mermaid then converts that text into SVG graphics.

For architecture diagrams specifically, mermaid.js uses the flowchart syntax (previously called "graph") as the primary diagram type. You define components as nodes and draw relationships between them using arrows and link text. The result is a clean, readable diagram that lives alongside your code.

Here's the simplest possible architecture diagram in mermaid markup:

graph TD
  Client --> API_Gateway
  API_Gateway --> Auth_Service
  API_Gateway --> Data_Service
  Data_Service --> Database

This produces a top-down flowchart showing a client connecting through an API gateway to authentication and data services, with the data service reaching a database. Five lines of text. One clear diagram.

Why would someone use mermaid.js instead of drawing tools?

Traditional diagramming tools like draw.io or Lucidchart work fine for one-off visuals. But they create binary files that don't diff well in Git, can't be edited by multiple people simultaneously in a text-based review, and often require a paid account for team features.

Mermaid.js diagrams are plain text. That means:

  • Version control works naturally. You can see exactly what changed in a pull request diff.
  • Anyone can edit them. No special software or license required just a text editor.
  • They live with your docs. Markdown files on GitHub, GitLab, and many documentation platforms render mermaid diagrams natively.
  • They stay up to date. When the architecture changes, updating the diagram takes seconds, not minutes of redrawing boxes.

If your team already works with text-based tools and wants to keep documentation close to code, mermaid.js fits that pattern well. For teams comparing approaches, our guide to architecture diagram markup standards covers how different markup approaches compare.

What does a real mermaid.js architecture diagram look like?

Let's walk through a practical example a typical three-tier web application architecture:

graph TD
  User["👤 User / Browser"] --> CDN["CloudFront CDN"]
  CDN --> LB["Load Balancer"]
  LB --> Web1["Web Server 1"]
  LB --> Web2["Web Server 2"]
  Web1 --> App["Application Server"]
  Web2 --> App
  App --> Cache["Redis Cache"]
  App --> DB["PostgreSQL Database"]
  App --> Queue["Message Queue"]
  Queue --> Worker["Background Worker"]
  Worker --> DB

This shows the full request path from a user's browser through a CDN, load balancer, web servers, application layer, caching, database, and a background processing queue. Each node has a descriptive label, and the arrows show the direction of data flow.

Notice that mermaid handles branching paths automatically. When the load balancer connects to two web servers, mermaid lays them out side by side without any manual positioning.

How do you shape and style nodes in architecture diagrams?

Plain rectangular boxes work for quick sketches, but real architecture diagrams benefit from visual distinction. Mermaid.js supports different node shapes by changing the bracket syntax:

  • Node["Label"] rectangular box (default)
  • Node("Label") rounded rectangle
  • Node{"Label"} diamond (decision point)
  • Node[/"Label"/] parallelogram (input/output)
  • Node(("Label")) circle

For architecture diagrams, rounded rectangles work well for services, rectangles for databases and storage, and diamonds for decision logic. Here's how that looks in practice:

graph TD
  Request("HTTP Request") --> Auth{"Authenticated?"}
  Auth -->|Yes| API("API Handler")
  Auth -->|No| Reject["401 Unauthorized"]
  API --> DB[/"Database"/]

The labels on arrows (like "Yes" and "No") help readers follow the logic without guessing. For more shape options and advanced styling, see our mermaid.js architecture diagram markup examples collection with additional patterns.

Can you diagram microservices architecture with mermaid.js?

Yes, and this is where mermaid.js proves especially useful. Microservices architectures involve many interconnected services, and keeping a diagram current by hand is tedious. With mermaid markup, you can represent an entire microservices system:

graph TD
  Client["Mobile App"] --> API_GW["API Gateway"]
  Web["Web App"] --> API_GW
  
  API_GW --> UserSvc["User Service"]
  API_GW --> OrderSvc["Order Service"]
  API_GW --> ProductSvc["Product Service"]
  API_GW --> PaymentSvc["Payment Service"]
  
  UserSvc --> UserDB[("Users DB")]
  OrderSvc --> OrderDB[("Orders DB")]
  ProductSvc --> ProductDB[("Products DB")]
  PaymentSvc --> PaymentDB[("Payments DB")]
  
  OrderSvc -->|"events"| EventBus["Event Bus"]
  PaymentSvc -->|"events"| EventBus
  EventBus -->|"events"| NotifySvc["Notification Service"]
  EventBus -->|"events"| AnalyticsSvc["Analytics Service"]

This shows both the synchronous API calls and the asynchronous event-driven communication between services. The "events" labels on the arrows distinguish message-based communication from direct API calls.

When you compare this to PlantUML's approach to architecture diagrams, mermaid.js tends to be more concise for basic diagrams but offers fewer layout control options for complex arrangements.

How do you add direction and subgraphs to organize complex diagrams?

Two features make large architecture diagrams readable: direction control and subgraphs.

Controlling diagram direction

The first word after graph sets the flow direction:

  • graph TD top to bottom (most common for layered architectures)
  • graph LR left to right (good for pipeline or flow-based architectures)
  • graph BT bottom to top
  • graph RL right to left

Grouping components with subgraphs

Subgraphs let you draw boundaries around logical groups. This is critical for showing which components belong to which layer, domain, or network zone:

graph TD
  subgraph Frontend
    Web["Web App"]
    Mobile["Mobile App"]
  end
  
  subgraph Backend
    API["REST API"]
    Worker["Background Jobs"]
  end
  
  subgraph Data
    Cache[("Redis")]
    DB[("PostgreSQL")]
  end
  
  Web --> API
  Mobile --> API
  API --> Cache
  API --> DB
  Worker --> DB

This produces three labeled, bordered groups. Readers can immediately see that the frontend components talk to the backend, which connects to the data layer. Without subgraphs, a diagram with the same nodes would look like a flat, harder-to-read mess.

What are the most common mistakes people make?

After working with mermaid.js diagrams across many projects, these mistakes come up repeatedly:

  1. Too many nodes in one diagram. A diagram with 30+ nodes becomes hard to read even with subgraphs. Split it into multiple focused diagrams instead one per service boundary or user flow.
  2. Missing arrow labels. An architecture diagram without labeled connections forces readers to guess whether a link represents an HTTP call, a database query, a message queue event, or a gRPC stream. Always label your connections.
  3. Inconsistent naming. Mixing styles like user-service, UserService, and user_svc in one diagram creates confusion. Pick one convention and stick with it.
  4. Using special characters in node IDs. Node identifiers can't contain spaces, dots, or hyphens without causing parsing errors. Use underscores in IDs and put the display name in quotes: Auth_Service["Auth Service"].
  5. Forgetting that mermaid renders top-down by default. If your architecture is naturally horizontal (like a pipeline), always specify graph LR explicitly.
  6. Not testing before committing. Mermaid syntax errors are silent the diagram just won't render. Use the Mermaid Live Editor to validate your markup before adding it to documentation.

How do you include mermaid diagrams in documentation?

Mermaid.js works in several common environments without extra setup:

  • GitHub. GitHub renders mermaid code blocks natively in Markdown files, issues, and pull requests. Just wrap your markup in a ```mermaid code fence.
  • GitLab. GitLab also supports mermaid rendering in Markdown and wikis.
  • Static site generators. Tools like Docusaurus, MkDocs (with plugins), and Hugo can render mermaid diagrams in documentation pages.
  • Notion and Confluence. Both platforms support mermaid blocks through built-in features or plugins.

For environments that don't support native rendering, the mermaid CLI tool (@mermaid-js/mermaid-cli) can generate SVG or PNG files from your markup files. This is useful for PDF exports or presentations.

Quick-start checklist for your first architecture diagram

Before you write your first line of mermaid markup, run through this checklist:

  1. List your components. Write down every service, database, queue, and external system you want to show.
  2. Map the connections. Draw (even on paper) which component talks to which, and how (API call, event, database query).
  3. Pick a direction. Top-down for layered architectures, left-to-right for pipelines or flows.
  4. Group related components. Decide which nodes belong in subgraphs by domain, layer, or deployment environment.
  5. Write the markup. Start with the subgraphs, then add connections. Keep node IDs short and display labels descriptive.
  6. Validate in the live editor. Paste your markup at mermaid.live to check the output before committing.
  7. Commit with your code. Save the diagram file alongside the code or documentation it describes. Review it in your next pull request like any other change.

Start with a single, focused diagram maybe just the request flow for one feature and expand from there. Keeping diagrams small and up to date is far more valuable than creating one massive diagram that nobody maintains.