Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active June 10, 2025 13:22
Show Gist options
  • Save Integralist/228d1c8b0d309a41de67afe09111f4eb to your computer and use it in GitHub Desktop.
Save Integralist/228d1c8b0d309a41de67afe09111f4eb to your computer and use it in GitHub Desktop.
Mermaid Diagram Examples #diagrams

https://mermaid.js.org/
https://mermaid.live/

---
title: Sequence Diagram example
---
sequenceDiagram
    autonumber
    participant cl AS Client
    participant avs AS API VCL Service (Edge)
    participant dag AS MyApp API Gateway (Edge)
    participant ag AS Auth Gateway (Control Plane)
    participant er AS Entity Registry (Control Plane)
    participant da AS MyApp API (Control Plane)
    
    %% below we put a note across MULTIPLE actors
    note over ag,da: here is my note

    cl->>+avs: Initial Request
    avs->>+dag: Proxy Request
    alt JWT Expired
        dag<<-->>ag: Exchange API Key for JWT 
    end
    alt EntityID Not Found
        dag<<-->>er: Look up EntityId associated with CustomerId
    end
    dag->>+da: Proxy request to Origin
    da->>-dag: Origin response
    dag->>-avs: Respond to API VCL Service
    avs->>-cl: Respond to client
Loading

Note

The yellow box is rendered by use of + and - before the target names.
e.g. cl->>+avs: Initial Request finishes with avs->>-cl: Respond to client

Tip

Use autonumber to automatically number lines!

Tip

You can comment out lines using %%.

---
title: Instant Onboarding - API Integration
---
sequenceDiagram
    participant ui AS MyApp UI
    participant dag AS MyApp API Gateway (Edge)
    participant da AS MyApp API (Control Plane)
    participant rd AS Redis (Cache)
    participant dns AS DNS (Resolution)

    ui->>dag: Initial request
    note right of ui: GET /internal/domains/v1/tools/lookup/{fqdn}
    dag->>+da: Proxy request to the API
    da->>rd: Lookup domain in cache
    alt No cache record Found
        note right of da: Query CNAME and SOA records
        da<<-->>dns: DNS lookup
    end
    da->>-ui: JSON response
Loading
---
title: Flowchart example
---
flowchart TD
    A[Christmas] -->|Get money| B(Go shopping)
    B --> C{Let me think}
    C -->|One| D[Laptop]
    C -->|Two| E[iPhone]
    C -->|Three| F[fa:fa-car Car]
Loading

Note

TB - Top to bottom
TD - Top-down/ same as top to bottom
BT - Bottom to top
RL - Right to left
LR - Left to right

Tip

For a flowchart, you can use either flowchart or graph (see below for example).

---
title: DNS CNAME/SOA Lookup Flow
---
graph TD
    A[Check for CNAME] --> B{CNAME Exists?};
    B -- Yes --> C[Check SOA of CNAME];
    B -- No --> D[Check SOA of APEX];
    C --> E{RNAME and MNAME match?};
    E -- Yes --> F[Return Hostname];
    E -- No --> G{Known RNAME match?};
    G -- Yes --> H[Return RNAME Hostname];
    G -- No --> I{Known MNAME match?};
    I -- Yes --> J[Return MNAME Hostname];
    I -- No --> D;
    D --> K{RNAME and MNAME match?};
    K -- Yes --> L[Return Hostname];
    K -- No --> M{Known RNAME match?};
    M -- Yes --> N[Return RNAME Hostname];
    M -- No --> O{Known MNAME match?};
    O -- Yes --> P[Return MNAME Hostname];
    O -- No --> Q[Return empty string];
Loading
---
title: Current TLS API Overview
---
graph LR
    A@{ shape: circle, label: "Customer" } --> B(TLS API);
    B --> C[[Spotless]];
    C --> D{API Routing};
    D --> E@{ shape: braces, label: "Activations" };
    D --> F@{ shape: braces, label: "Bulk" };
    D --> G@{ shape: braces, label: "Certificates" };
    D --> H@{ shape: braces, label: "Configuration" };
    D --> I@{ shape: braces, label: "Domains" };
    D --> J@{ shape: braces, label: "Mutual Authentication" };
    D --> K@{ shape: braces, label: "Private Keys" };
    D --> L@{ shape: braces, label: "Subscriptions" };
    L --> M{Certificate Authority CA};
    M --> N[[Let's Encrypt]]
    M --> O[[Certainly]]
    M --> P[[GlobalSign]]
Loading
---
title: Class Diagram example
---
classDiagram
    note "From Duck till Zebra"
    Animal <|-- Duck
    note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
    class Duck{
        +String beakColor
        +swim()
        +quack()
    }
    class Fish{
        -int sizeInFeet
        -canEat()
    }
    class Zebra{
        +bool is_wild
        +run()
    }
Loading
---
title: State Diagram example
---
stateDiagram-v2
    [*] --> Still
    Still --> [*]

    Still --> Moving
    Moving --> Still
    Moving --> Crash
    Crash --> [*]
Loading
pie title Pie Chart example
    "Dogs" : 386
    "Cats" : 85
    "Rats" : 15
Loading
---
title: API Request Flow
---
erDiagram
    Customer ||--o{ TLSAPI : makes-requests-to
    TLSAPI ||--o{ SpotlessBackendAPI : communicates-with
    SpotlessBackendAPI {
        string API_Routing
    }
    SpotlessBackendAPI ||--o{ Activations : routes-to
    SpotlessBackendAPI ||--o{ Bulk : routes-to
    SpotlessBackendAPI ||--o{ Certificates : routes-to
    SpotlessBackendAPI ||--o{ Configurations : routes-to
    SpotlessBackendAPI ||--o{ Domains : routes-to
    SpotlessBackendAPI ||--o{ MutualAuthentication : routes-to
    SpotlessBackendAPI ||--o{ PrivateKeys : routes-to
    SpotlessBackendAPI ||--o{ Subscriptions : routes-to
    Subscriptions ||--o{ CertificateAuthority : communicates-with
Loading
sequenceDiagram
    participant Customer
    participant Spotless
    participant Ascerta
    participant Queue
    participant Worker

    Customer->>Spotless: POST /tls/subscriptions
    Spotless->>+Ascerta: https://<hostname>/internal/tls/v2/certs/...
    Note right of Spotless: include callback url
    par
        Ascerta-->>Queue: send request
    end
    Note right of Ascerta: include callback url
    Ascerta->>-Spotless: response
    Spotless->>Customer: 201 Created
    par
        Worker<<->>Queue: get item
        Worker->>Worker: do work
        Worker->>Spotless: https://<hostname>/internal/tls/v2/certs/...
        Note right of Spotless: the callback url
    end
Loading
---
title: NSQ Infrastructure
---
graph LR
    subgraph "Producer"
        A[API] -- push to topic --> CP((topic: priority))
        A -- push to topic --> CS((topic: standard))
        A -- push to topic --> CSP((topic: special))

        %% nsqd is the daemon that receives, queues, and distributes messages. 
        %% It acts as the message queue server.
        CP & CS & CSP -- send message --> N[nsqd]
    end

    subgraph " "
        %% nsqlookupd provides a directory service, 
        %% allowing consumers to find the nsqd instances that are producing messages 
        %%for a specific topic.
        N -- register topic --> L[nsqlookupd]
    end

    subgraph "Consumers"
        %% The consumers are trying to discover the nsqd instances 
        %% that are handling the specific topic they're interested in. 
        L <-- discover producers --> WP@{ shape: procs, label: "priority workers"}
        L <-- discover producers --> WS@{ shape: procs, label: "standard workers"}
        L <-- discover producers --> WSP@{ shape: procs, label: "special workers"}

        WP & WS & WSP <-- retrieve message --> N
    end
Loading

Below is an example of drawing boxes around specific parts of a system...

sequenceDiagram
    participant EU as End User
    participant RR as Recursive Resolver
    participant Root as Root Servers
    participant TLD as .com TLD Servers
    participant DS as DNSimple Servers <br/> (IPs via Glue Records for nsX.example.com)
    participant Cust as Customer
    participant UI as Example UI
    participant BE as Example Facade API Service
    participant API as DNSimple API
    participant DB as DNSimple Database

    box LightBlue DNS Resolution Process (Query for www.customerdomain.com)
        participant EU
        participant RR
        participant Root
        participant TLD
    end

    box Pink Record Management Process (Customer updates DNS)
        participant Cust
        participant UI
        participant BE
        participant API
    end

    Note over EU, DS: Initial Setup Prerequisite (Not Shown):<br/>1. Vanity NS (nsX.example.com) configured in DNSimple.<br/>2. Glue Records created at example.com's registrar mapping nsX.example.com to DNSimple IPs.<br/>3. customerdomain.com's NS records point to nsX.example.com.

    %% === DNS Resolution Flow ===
    EU->>+RR: Resolve www.customerdomain.com?
    RR->>+Root: Who handles .com?
    Root-->>-RR: TLD Server IPs
    RR->>+TLD: Who handles customerdomain.com?
    TLD-->>-RR: NS: ns1.example.com @ DNSimple_IP1<br/>NS: ns2.example.com @ DNSimple_IP2<br/>(Info via Glue Records)
    RR->>+DS: (Query sent to DNSimple_IP1) A record for www.customerdomain.com?
    DS-->>-RR: A record is 192.0.2.100
    RR-->>-EU: www.customerdomain.com is 192.0.2.100
    EU->>(Web Server): Connect to 192.0.2.100

    %% === Record Management Flow ===
    Cust->>+UI: Login & Navigate to manage.example.com
    Cust->>UI: Request Add/Update Record (e.g., TXT _foo="bar")
    UI->>+BE: Submit Record Change Request (domain, type, name, content)
    BE->>+API: Create/Update Record via DNSimple API<br/>(Zone: customerdomain.com, Record Details)
    API->>+DB: Store/Update record data in DNSimple's database
    Note over DB, DS: DNSimple internal propagation<br/>updates authoritative servers (DS).
    DB-->>-API: Confirmation of data update
    API-->>-BE: Success Response (e.g., Record ID)
    BE-->>-UI: Operation Successful
    UI-->>-Cust: Display success message / updated record list

    Note right of DS: DNSimple Servers (DS)<br/>now serve the<br/>new/updated record<br/>for future queries.
Loading

Example of complex architecture with <br> for line breaks:

graph TD
    subgraph "User Interaction"
        User[User/Customer]
    end

    subgraph "Example DNS Platform"
        ManagementService[Example DNS Management Service API/UI]
        CentralDB[("Central Database: stores zones with 'account' column for partition_id")]
        
        subgraph "DNS Partition ..N"
            PDNSN[PowerDNS Instance for PN <br><br> config: SELECT ... WHERE account='PN_id']
            NS_PN_Set[NS Servers for P..N: <br><br> nsn1.your-dns.com nsn2.your-dns.com]
        end
        subgraph "DNS Partition 2"
            PDNS2[PowerDNS Instance for P2 <br><br> config: SELECT ... WHERE account='P2_id']
            NS_P2_Set[NS Servers for P2: <br><br> nsb1.your-dns.com nsb2.your-dns.com]
        end
        subgraph "DNS Partition 1"
            PDNS1[PowerDNS Instance for P1 <br><br> config: SELECT ... WHERE account='P1_id']
            NS_P1_Set[NS Servers for P1: <br><br> nsa1.your-dns.com nsa2.your-dns.com]
        end
    end

    subgraph "External DNS Infrastructure"
        Registrar[Domain Registrar]
        UserCurrentDNS[User's Current/External DNS; for verification if needed]
    end

    User -- Manages Zones via --> ManagementService
    ManagementService -- Reads/Writes Zone Config --> CentralDB
    
    PDNS1 -- Reads Zone Data <br> (filtered for P1) --> CentralDB
    PDNS2 -- Reads Zone Data <br> (filtered for P2) --> CentralDB
    PDNSN -- Reads Zone Data <br> (filtered for PN) --> CentralDB
    
    NS_P1_Set -- Served by --> PDNS1
    NS_P2_Set -- Served by --> PDNS2
    NS_PN_Set -- Served by --> PDNSN

    User -- Creates Verification Record --> UserCurrentDNS
    User -- Updates NS Records --> Registrar

    ManagementService -- Verification Check --> UserCurrentDNS

    style User fill:#aliceblue,stroke:#333,stroke-width:2px
    style ManagementService fill:#lightcyan,stroke:#333,stroke-width:2px
    style CentralDB fill:#honeydew,stroke:#333,stroke-width:2px
    style PDNS1 fill:#mistyrose,stroke:#333,stroke-width:2px
    style PDNS2 fill:#mistyrose,stroke:#333,stroke-width:2px
    style PDNSN fill:#mistyrose,stroke:#333,stroke-width:2px
    style NS_P1_Set fill:#lemonchiffon,stroke:#333,stroke-width:2px
    style NS_P2_Set fill:#lemonchiffon,stroke:#333,stroke-width:2px
    style NS_PN_Set fill:#lemonchiffon,stroke:#333,stroke-width:2px
    style Registrar fill:#thistle,stroke:#333,stroke-width:2px
    style UserCurrentDNS fill:#whitesmoke,stroke:#333,stroke-width:2px
Loading

Example of complex architecture using line colours and ~~~ to force a vertical rendering of the boxes within the "DNS Data Plan" subgraph:

flowchart TD
    subgraph user["User Interaction"]
        APIUser["User/Customer"]
        DNSUser["User/Customer"]
    end

    subgraph DNSControl["DNS Control Plane"]
        APIService["DNS API Service"]
        controlPlaneDB[("Control Plane Database: stores zone mappings, entityID information, partition mapping")]
    end

    subgraph pdnsInstance ["PowerDNS instance"]
        pdnsAPIN["PowerDNS Primary/Secondary"]
        pdnsDBN[("PowerDNS Partition N MySQL Database: stores zones, records, etc")]
        pdnsAPIN --> pdnsDBN
        pdnsDBNReplica[("PowerDNS Partition N MySQL Replica DB: stores zones, records, etc")]
        pdnsDBN -- Replication --> pdnsDBNReplica
        Note["Note: PowerDNS will act as a primary/secondary for a given zone, depending on the configuration"]
    end
    
    subgraph DNSDataPlane ["DNS Data Plane"]
        subgraph pdnsN["PDNS Partition..N"]
            origin_refN["origin instance"]
            control_refN["control instance"]
            transfer_refN["transfer instance"]
        end
        subgraph pdns2["PDNS Partition 2"]
            origin_ref2["origin instance"]
            control_ref2["control instance"]
            transfer_ref2["transfer instance"]
        end
        subgraph pdns1["PDNS Partition 1"]
            origin_ref1["origin instance"]
            control_ref1["control instance"]
            transfer_ref1["transfer instance"]
        end
        
        %% Vertical Layout Hint (i.e. force a vertical rendering of the boxes)
        pdns1 ~~~ pdns2
        pdns2 ~~~ pdnsN
    end

    subgraph externalDNSProvider["External DNS Platform"]
    end

    subgraph EdgeDNS["DNS Edge"]
        subgraph cacheN["Cache Node ..N"]
            xdnsN["xdns (dns proxy): <br> Filters invalid packets"]
            dnsdistN["dnsdist: authoritative DNS cache/proxy"]
        end
        subgraph cache2["Cache Node 2"]
            xdns2["xdns (dns proxy): <br> Filters invalid packets"]
            dnsdist2["dnsdist: authoritative DNS cache/proxy"]
        end
        subgraph cache1["Cache Node 1"]
            xdns1["xdns (dns proxy): <br> Filters invalid packets"]
            dnsdist1["dnsdist: authoritative DNS cache/proxy"]
        end
        xdns1 <-- valid query --> dnsdist1
        dnsdist1 -- Cache misses <br> Xproxy encoded --> origin_ref1
        xdns2 <-- valid query --> dnsdist2
        dnsdist2 <-- Cache misses <br> Xproxy encoded ---> origin_ref2
        xdnsN <-- valid query --> dnsdistN
        dnsdistN <-- Cache misses <br> Xproxy encoded ---> origin_refN
    end
    
    %% Connections
    APIUser -- Manages Zones via API --> APIService
    APIUser -- Manages Zones on External DNS Provider --> externalDNSProvider
    DNSUser -- Incoming DNS Queries --> EdgeDNS
    
    APIService -- Route DNS request to PowerDNS control instance ---> control_refN
    APIService -- Route DNS request to PowerDNS control instance ---> control_ref2
    APIService -- Route DNS request to PowerDNS control instance ---> control_ref1
    APIService -- Check DB for customer information and mapping--> controlPlaneDB
    
    externalDNSProvider -- Replicates records via XFR --> transfer_ref1
    externalDNSProvider -- Replicates records via XFR --> transfer_ref2
    externalDNSProvider -- Replicates records via XFR --> transfer_refN
    
    %% Links to PowerDNS Instance
    origin_refN -- "is a" --> pdnsInstance
    control_refN -- "is a" --> pdnsInstance
    transfer_refN -- "is a" --> pdnsInstance
    origin_ref1 -- "is a" --> pdnsInstance
    control_ref1 -- "is a" --> pdnsInstance
    transfer_ref1 -- "is a" --> pdnsInstance
    origin_ref2 -- "is a" --> pdnsInstance
    control_ref2 -- "is a" --> pdnsInstance
    transfer_ref2 -- "is a" --> pdnsInstance

    %% Links for origin instances
    linkStyle 4 stroke:red,stroke-width:2px,color:grey;
    linkStyle 5 stroke:red,stroke-width:2px,color:grey;
    linkStyle 6 stroke:red,stroke-width:2px,color:grey;
    linkStyle 7 stroke:red,stroke-width:2px,color:grey;
    linkStyle 8 stroke:red,stroke-width:2px,color:grey;
    linkStyle 9 stroke:red,stroke-width:2px,color:grey;
    linkStyle 12 stroke:red,stroke-width:2px,color:grey;
    linkStyle 20 stroke:red,stroke-width:2px,color:grey;
    linkStyle 23 stroke:red,stroke-width:2px,color:grey;
    linkStyle 26 stroke:red,stroke-width:2px,color:grey;

    %% Links for control instances
    linkStyle 10 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 13 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 14 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 15 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 16 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 21 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 24 stroke:blue,stroke-width:2px,color:grey;
    linkStyle 27 stroke:blue,stroke-width:2px,color:grey;

    %% Links for transfer instances
    linkStyle 11 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 17 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 18 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 19 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 22 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 25 stroke:orange,stroke-width:2px,color:grey;
    linkStyle 28 stroke:orange,stroke-width:2px,color:grey;
Loading

Here's a simplified version of the above:

flowchart TD
    subgraph user["Customer Interaction"]
        APIUser["API User"]
        DNSUser["DNS User"]
        ExternalUser["External User"]
    end

    subgraph DNSControl["DNS Control Plane"]
        APIService["DNS API Service"]
        controlPlaneDB[("Control Plane Database: stores zone mappings, entityID information, partition mapping")]
    end
    
    subgraph DNSDataPlane ["DNS Data Plane"]
        subgraph pdnsN["Partitions ..N"]
            origin["PowerDNS:<br>origin instance"]
            control["PowerDNS:<br>control instance"]
            transfer["PowerDNS:<br>transfer instance"]

            pdnsDBOrigin[("PowerDNS:<br>Database")]
            pdnsDBControl[("PowerDNS:<br>Database")]
            pdnsDBTransfer[("PowerDNS:<br>Database")]

            origin --> pdnsDBOrigin
            control --> pdnsDBControl
            transfer --> pdnsDBTransfer
        end
    end

    DNSDataPlane --> pdnsInstance

    subgraph pdnsInstance ["PowerDNS instance"]
        pdnsAPIN["PowerDNS Primary/Secondary"]
        pdnsDBN[("PowerDNS Partition N MySQL Database: stores zones, records, etc")]
        pdnsAPIN --> pdnsDBN
        pdnsDBNReplica[("PowerDNS Partition N MySQL Replica DB: stores zones, records, etc")]
        pdnsDBN -- Replication --> pdnsDBNReplica
        Note["Note: PowerDNS will act as a primary/secondary for a given zone, depending on the configuration"]
    end

    subgraph externalDNSProvider["External DNS Platform"]
    end

    subgraph EdgeDNS["DNS Edge"]
        subgraph cacheN["Cache Node ..N"]
            xdnsN["xdns (dns proxy):<br>filters invalid packets"]
            dnsdistN["dnsdist:<br>authoritative DNS cache/proxy"]
        end
        xdnsN <-- valid query --> dnsdistN
        dnsdistN <-- cache miss<br>(xproxy encoded) ---> pdnsN
    end
    
    %% Connections
    APIUser -- Manages Zones via API --> APIService
    ExternalUser -- Manages Zones on External DNS Provider --> externalDNSProvider
    DNSUser -- Incoming DNS Queries --> EdgeDNS
    
    APIService -- Route DNS request to PowerDNS control instance ---> control
    APIService -- Route DNS request to PowerDNS control instance ---> control
    APIService -- Route DNS request to PowerDNS control instance ---> control
    APIService -- Check DB for customer information and mapping--> controlPlaneDB
    
    externalDNSProvider -- Replicates records via XFR --> transfer
    externalDNSProvider -- Replicates records via XFR --> transfer
    externalDNSProvider -- Replicates records via XFR --> transfer
Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment