Skip to main content
Engineering/system-diagram

System Diagram

You need a high-level architecture or system diagram.

Use this when you need a shared visual of system architecture — from a codebase overview, RFC, meeting transcript, existing diagram, or a mix of all four. The output is a C4-style or box-and-arrow diagram rendered in Mermaid syntax, with optional export to Miro or FigJam.

Process

Step 1: Gather inputs

Ask the user:

  1. Input sources — what should the diagram be based on? Accept one or more:
    • Codebase overview or file tree
    • RFC, ADR, or design document
    • Meeting transcript or conversation notes
    • Existing diagram (text description, image, or Mermaid code)
    • Verbal description of the system
  2. Diagram level — which C4 abstraction level?
    • Context (default) — system and its external actors/dependencies
    • Container — applications, data stores, and their interactions within one system
    • Component — internal structure of a single container
    • Deployment — infrastructure and deployment topology
  3. Focus area — the whole system, or a specific subsystem/flow?
  4. Notation preference -- C4 style (recommended), box-and-arrow, or sequence diagram?
  5. Perspective -- as-is (current state, default) or to-be (future state / proposed solution)? Future-state diagrams add sections for proposed changes, migration considerations, and decision rationale.
  6. Visual output -- beyond the Mermaid markdown?
    • Markdown only (default) — Mermaid code block in the saved file
    • FigJam diagram — visual diagram via Figma MCP (flowchart format)
    • Miro board — document posted to a Miro board
    • PDF slide deck — branded PDF via Marp
    • Presentation (Google Slides) — via Gamma
    • Multiple — any combination

Default to Context level, full system, C4 style, markdown only.

Step 2: Extract system elements

From the provided inputs, identify:

Actors and external systems:

  • Users, roles, or personas that interact with the system
  • External services, APIs, third-party integrations
  • Data sources and sinks outside the system boundary

Internal components:

  • Applications, services, microservices
  • Databases, caches, message queues
  • Batch jobs, scheduled tasks, background workers

Relationships:

  • Synchronous calls (API, RPC, HTTP)
  • Asynchronous messaging (events, queues, pub/sub)
  • Data flows (reads, writes, replication)
  • Dependencies (uses, depends on, authenticates via)

Boundaries:

  • System boundary (what's "ours" vs. external)
  • Subsystem or bounded context boundaries
  • Trust boundaries (internal network vs. public)
  • Team ownership boundaries (if known)

For each element, capture:

  • Name — clear, consistent label
  • Technology — language, framework, or platform (if known)
  • Purpose — one-line description of what it does
  • Relationships — what it connects to and how

Flag any elements with [INFERRED] if they came from indirect evidence rather than explicit documentation.

If perspective is "to-be" (future state): Also identify proposed new components, components being modified, and components being deprecated. Tag each with [NEW], [MODIFIED], or [DEPRECATED].

Step 3: Compose the Mermaid diagram

Generate the diagram using Mermaid syntax appropriate to the selected level and notation:

For C4 Context diagrams:

graph TB
    subgraph "System Boundary"
        A["Service A<br/><i>Purpose</i>"]
        B["Service B<br/><i>Purpose</i>"]
    end
    User["Actor<br/><i>Role</i>"] -->|"Action"| A
    A -->|"Sync: API call"| B
    B -.->|"Async: Event"| C["External System<br/><i>Purpose</i>"]

For C4 Container diagrams:

graph TB
    subgraph "System Name"
        subgraph "Web Tier"
            WebApp["Web App<br/><i>React, TypeScript</i>"]
        end
        subgraph "API Tier"
            API["API Server<br/><i>Node.js, Express</i>"]
        end
        subgraph "Data Tier"
            DB[("Database<br/><i>PostgreSQL</i>")]
            Cache[("Cache<br/><i>Redis</i>")]
        end
    end
    WebApp -->|"HTTPS/JSON"| API
    API -->|"SQL"| DB
    API -->|"Read/Write"| Cache

Notation conventions:

  • Solid arrows (-->) = synchronous interaction
  • Dashed arrows (-.->) = asynchronous interaction
  • Rectangles = services, applications
  • Cylinders ([(" ")]) = data stores
  • Subgraphs = boundaries (system, subsystem, trust, team)
  • Labels on arrows = protocol or data description
  • <br/><i>italics</i> = technology stack under the name

If perspective is "to-be" (future state): Use dashed subgraph borders or a style annotation for proposed/new components vs. existing. After the diagram, include:

  • Proposed Changes -- list what is new, modified, or deprecated and why
  • Migration Considerations -- sequencing, data migration, cutover risks, rollback strategy
  • Decision Rationale -- link each proposed change to the problem it solves

Step 4: Add the legend and metadata

Include a legend explaining the notation used:


System Diagram: (System Name)

Date: (date) Level: (Context / Container / Component / Deployment) Perspective: (As-is / To-be) Sources: (list of input documents/sources used) Scope: (full system / specific subsystem or flow)

Diagram

(generated Mermaid code)

Legend

SymbolMeaning
Solid rectangleApplication or service
CylinderData store (database, cache, queue)
Solid arrow ()Synchronous interaction (API, RPC, HTTP)
Dashed arrow ()Asynchronous interaction (event, message, pub/sub)
Subgraph boundarySystem, subsystem, or trust boundary
[INFERRED] tagElement derived from indirect evidence — verify with team

Components

ComponentTypeTechnologyPurposeOwner
(Name)Service / DB / Queue / External(Stack)(One-line purpose)(Team, if known)

Interactions

FromToTypeProtocolDescription
(Component A)(Component B)Sync/Async(HTTP, gRPC, Kafka, etc.)(What data flows)

Boundaries

BoundaryContainsNotes
(Boundary name)(Components inside)(Trust level, team, etc.)

Inferred Elements

(List any components or relationships marked [INFERRED] with the evidence that led to the inference and what needs verification)

Open Questions

  • (Ambiguities in the source material)
  • (Missing information that would improve the diagram)
  • (Boundary decisions that need team input)

Step 4b: Link to architecture decisions

For each significant component or boundary in the diagram, connect it to the decision that shaped it:

### Architecture decision context

| Component / Boundary | Decision | Status | Rationale summary | Trade-offs |
|---------------------|----------|--------|-------------------|-----------|
| (component name) | (ADR title or decision description) | Active / Superseded / Proposed | (why this approach was chosen) | (what was given up) |

### Constraints annotated on diagram
- (component): (constraint -- e.g., "Must remain on-prem per compliance requirement")
- (boundary): (constraint -- e.g., "Team ownership split here due to org restructure")
- (relationship): (constraint -- e.g., "Sync call required -- event-driven not viable due to consistency requirements")

If ADRs exist, reference them by ID. If they don't, flag this as an opportunity: "These decisions are currently undocumented. Consider creating ADRs for the following architectural choices: ..."

Architecture evolution tracking: When the user requests a diagram update, preserve the previous version:

  • Add a **Version:** field to the metadata (v1, v2, etc.)
  • Note what changed and why in a ### Change log section
  • Offer to generate a before/after comparison diagram showing what shifted

Step 5: Generate visual outputs (optional)

If the user requested visual output beyond markdown, follow the visual-output-addon:

  • FigJam (Path D) — convert the Mermaid diagram to a flowchart. System diagrams map well to graph TB or graph LR Mermaid syntax, which FigJam supports natively.
  • Miro (Path C) — post the full diagram document (including tables and legend) as a Miro doc. For visual diagrams, use diagram_create with the Mermaid syntax.
  • PDF (Path A) — generate a slide deck with the diagram on one slide and the component/interaction tables on subsequent slides. Use the system diagram slides template if available.
  • Gamma (Path B) — generate a presentation with the diagram as the hero visual and supporting detail slides.

Step 6: Iterate

Ask the user:

  • Does this capture the system accurately?
  • Should I zoom into any component (move from Context → Container → Component)?
  • Are the [INFERRED] elements correct?
  • Should I add or remove any boundaries?
  • Want me to diagram an alternative architecture or a future-state version?

Offer to regenerate with adjustments. Each iteration appends to the same output file with a version note.

Uncertainty Policy

TopicToleranceAction
System boundary (what's in vs. out)LowSTOP and ask — wrong boundary = wrong diagram
Component existenceLowSTOP and ask if not clearly evidenced in inputs
Interaction type (sync vs. async)MediumAssume + flag [INFERRED] — team validates
Technology stack per componentHighBest guess or "(TBD)" — non-critical for structure
Team ownershipHighBest guess or omit — not always available
Data flow detailsMediumAssume + flag [INFERRED] — verify with engineers

Default: STOP and ask when a topic is not listed above.

Related skills

  • /boris-model — service relationship modeling from Event Storming (more process-oriented)
  • /event-storm — domain event discovery (upstream input)
  • /snap-document — detailed API/data documentation per bounded context
  • /architecture-discovery — full discovery skill set (Event Storm → Boris → SNAP)
  • /repository-discovery — map services to code repositories (complementary input)
  • /codependency-analyzer — extract code dependencies (complementary input)

Output locations

FormatLocationNotes
MarkdownConversation or saved fileAlways produced. Source of truth. Includes Mermaid code block.
FigJam diagramFigJamVia Figma MCP. Flowchart from Mermaid syntax.
Miro doc/diagramUser's specified Miro boardVia Miro MCP. Full document or visual diagram.
PDF./output/decks/(system-name)-system-diagram.pdfVia Marp. Branded slides.
Gamma/PPTXGamma URLVia Gamma MCP. Presentation format.
File./output/system-diagrams/(system-name)-(level)-(date).mdLocal file.

Example Output

Input

  • Input sources: RFC document (RFC-0041: Payment Processing Refactor) describing a move from monolithic checkout to discrete services, plus a verbal description: "We have a React storefront, a Node.js monolith that currently handles cart, orders, and payments, a PostgreSQL database, and we're adding Stripe for payment processing and sending order confirmation emails via SendGrid"
  • Company / system name: Meridian Commerce — CheckoutPlatform
  • Diagram level: Container (applications, data stores, and interactions within the system)
  • Perspective: To-be (future state per RFC-0041)
  • Visual output: Markdown only

Output

System Diagram: Meridian Commerce — CheckoutPlatform

Date: 2025-07-14 Version: v1 Level: Container Perspective: To-be (future state per RFC-0041) Sources: RFC-0041 (Payment Processing Refactor), verbal system description Scope: Full CheckoutPlatform system — cart, order, and payment flows


Diagram

graph TB
    Customer["Customer<br/><i>Authenticated web user</i>"]
    Stripe["Stripe<br/><i>Payment gateway API</i>"]
    SendGrid["SendGrid<br/><i>Transactional email</i>"]

    subgraph "Meridian Commerce — CheckoutPlatform"

        subgraph "Web Tier"
            Storefront["Storefront App<br/><i>React, TypeScript</i>"]
        end

        subgraph "API Tier"
            CartService["Cart Service<br/><i>Node.js, Express</i>"]
            OrderService["Order Service [NEW]<br/><i>Node.js, Express</i>"]
            PaymentService["Payment Service [NEW]<br/><i>Node.js, Express</i>"]
            NotificationWorker["Notification Worker [NEW]<br/><i>Node.js background worker</i>"]
            Monolith["Checkout Monolith [DEPRECATED]<br/><i>Node.js, Express</i>"]
        end

        subgraph "Messaging"
            EventBus[("Order Event Bus [NEW]<br/><i>AWS SQS</i>")]
        end

        subgraph "Data Tier"
            CartDB[("Cart DB<br/><i>PostgreSQL</i>")]
            OrderDB[("Order DB [NEW]<br/><i>PostgreSQL</i>")]
            PaymentDB[("Payment DB [NEW]<br/><i>PostgreSQL</i>")]
        end

    end

    Customer -->|"HTTPS"| Storefront
    Storefront -->|"REST/JSON"| CartService
    Storefront -->|"REST/JSON"| OrderService
    Storefront -->|"REST/JSON"| PaymentService

    CartService -->|"SQL"| CartDB
    OrderService -->|"SQL"| OrderDB
    PaymentService -->|"SQL"| PaymentDB

    OrderService -.->|"Async: order.confirmed event"| EventBus
    PaymentService -.->|"Async: payment.captured event"| EventBus
    EventBus -.->|"Async: consume events"| NotificationWorker

    PaymentService -->|"HTTPS: charge / refund"| Stripe
    NotificationWorker -->|"HTTPS: send email"| SendGrid

Legend

SymbolMeaning
Solid rectangleApplication or service
CylinderData store (database, queue)
Solid arrow ()Synchronous interaction (REST, SQL)
Dashed arrow ()Asynchronous interaction (event, message)
Subgraph boundaryTier or system boundary
[NEW] tagComponent introduced in RFC-0041
[DEPRECATED] tagComponent to be decommissioned post-migration
[INFERRED] tagElement from indirect evidence — verify with team

Components

ComponentTypeTechnologyPurposeOwner
Storefront AppServiceReact, TypeScriptCustomer-facing checkout UIFrontend Guild
Cart ServiceServiceNode.js, ExpressManages cart state and item pricingCommerce Team
Order Service [NEW]ServiceNode.js, ExpressCreates and tracks orders; split from monolithCommerce Team
Payment Service [NEW]ServiceNode.js, ExpressHandles charge, refund, and payment state via StripePayments Team
Notification Worker [NEW]WorkerNode.jsConsumes order/payment events; sends confirmation emailsCommerce Team
Checkout Monolith [DEPRECATED]ServiceNode.js, ExpressCurrent combined cart/order/payment handler; retiring post-RFCCommerce Team
Order Event Bus [NEW]QueueAWS SQSDecouples order and payment events from notification deliveryPlatform Eng
Cart DBDatabasePostgreSQLPersists cart sessions and line itemsCommerce Team
Order DB [NEW]DatabasePostgreSQLPersists order records and status historyCommerce Team
Payment DB [NEW]DatabasePostgreSQLPersists payment intents, charge IDs, and refund recordsPayments Team
StripeExternalREST APIPayment gateway — tokenization, charging, refundsExternal
SendGridExternalREST APITransactional email delivery for order confirmationsExternal

Interactions

FromToTypeProtocolDescription
Storefront AppCart ServiceSyncREST/JSONAdd/update/remove cart items
Storefront AppOrder ServiceSyncREST/JSONSubmit order from cart
Storefront AppPayment ServiceSyncREST/JSONInitiate and confirm payment
Cart ServiceCart DBSyncSQLRead/write cart sessions
Order ServiceOrder DBSyncSQLPersist order records and status
Payment ServicePayment DBSyncSQLStore charge IDs, payment intent state
Payment ServiceStripeSyncHTTPSCreate charge, capture payment, process refunds
Order ServiceOrder Event BusAsyncAWS SQSPublish order.confirmed event on successful order creation
Payment ServiceOrder Event BusAsyncAWS SQSPublish payment.captured event on successful charge
Order Event BusNotification WorkerAsyncAWS SQSDeliver events to worker for email dispatch
Notification WorkerSendGridSyncHTTPSSend order confirmation and payment receipt emails

Boundaries

BoundaryContainsNotes
Web TierStorefront AppPublic-facing; served via CDN
API TierCart Service, Order Service, Payment Service, Notification Worker, Checkout MonolithInternal network; services communicate via direct REST during migration
MessagingOrder Event BusAWS-managed; async decoupling between services and notification layer
Data TierCart DB, Order DB, Payment DBOne database per service post-migration (per RFC-0041 bounded context split)
ExternalStripe, SendGridOutside system boundary; accessed over public HTTPS

Proposed Changes (RFC-0041)

  • [NEW] Order Service — cart-to-order submission logic extracted from the monolith to enable independent scaling and deployment
  • [NEW] Payment Service — payment processing extracted and wired directly to Stripe, removing monolith's Stripe dependency
  • [NEW] Notification Worker — decoupled from request path; consumes SQS events so email failures don't block checkout
  • [NEW] Order Event Bus (SQS) — introduces async event spine; enables future consumers (loyalty, analytics) without modifying core services
  • [NEW] Order DB / Payment DB — separate schemas enforce bounded context isolation; eliminates cross-domain joins present in the current shared PostgreSQL instance
  • [DEPRECATED] Checkout Monolith — to be decommissioned after all traffic is routed through replacement services