DEV Community

Cover image for You Asked, I Coded: How I Turned AWS Architecture into a Diagram Using Code
Romina Mendez
Romina Mendez

Posted on

2 1 1 1 1

You Asked, I Coded: How I Turned AWS Architecture into a Diagram Using Code

A few days ago, someone left a comment on my previous article, a post that turned out to be very popular, reaching over 47K views and earning 300 GitHub stars ⭐️.
❤️ I want to sincerely thank every single reader who took the time to read, leave feedback, and star the repository.
Your support truly motivates me to keep writing, sharing, and growing with the community.

Image description


🙃 A Reader’s Question That Inspired This Post

👤 @reader · 📅 May 2 ,2025

Hey Romina, would you please make this diagram using Diagram as Code?
🔗 Link to the original diagram

Haven’t read my first article?

If you’re new to Diagram-as-Code, I highly recommend starting with my introductory tutorial.


What is Diagram-as-Code?

Let’s go over a quick introduction to Diagram-as-Code.

Diagram-as-Code is an approach that allows you to define diagrams through code instead of drawing them manually.
This method makes it possible to version, update, and maintain visual representations just like any other software artifact.

For a more in depth explanation, feel free to check out my previous article.


In this tutorial I will cover:

  1. 🔧 Key Components: Diagram, Cluster, and Node
  2. 🎨 Styling with graph_attr
  3. ☁️ Creating an AWS Three-Tier Web Architecture

1. 🔧 Diagram-as-Code: Key Components

To replicate the AWS architecture, we’ll use three primary objects from the diagrams library:

Component Description
Diagram The canvas or global graph context
Cluster A grouped section like a VPC, tier, or AZ
Node An infrastructure element (e.g., EC2, RDS, S3, etc.)

2. 🎨 Styling with graph_attr

To create more advanced or customized diagrams, we can modify attributes like colors, fonts, and layout.
Graphviz (the underlying engine) supports styling attributes similar to CSS.

Below are the attributes used in this tutorial:

Attribute Purpose Example
fillcolor Background color "lightblue" or "#000000"
pencolor Border color "#12b886"
penwidth Border thickness "2"
fontname Font style "Helvetica-Bold"
fontsize Font size "14"
labeljust Text alignment "c" (center)
splines Arrow shape "curved"

☁️ 3. Challenge: Recreate an AWS Workshop Diagram

1. Original Architecture Diagram

The following image comes from the AWS workshop repository:

link

Architecture Image

2. Code

Here is the code I used to recreate the image above.
I customized the appearance of the different clusters using graph_attr.

🐍 python

from diagrams import Diagram, Cluster,Node
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB, InternetGateway
from diagrams.aws.database import Aurora
from diagrams.aws.general import Users
from IPython.display import Image
from IPython.display import SVG, display

_cluster_layers_graph_attr ={"style": "filled",
                             "fillcolor": "lightblue",
                             "fontname": "Helvetica-Bold",
                             "fontsize": "18",
                             "penwidth": "2",
                             "pencolor":"#000000",
                             "labeljust": "c",
                             "fillcolor":"#a5d8ff"
                             }

_public_subnet_graph_attr ={"style": "filled", 
                            "fillcolor": "white",
                            "pencolor":"#12b886",
                            "fontcolor": "#12b886" ,
                            "fontname": "Helvetica-Bold",
                            "penwidth": "4",
                            "fontsize": "14"
                            }

_private_subnet_graph_attr ={"style": "filled", 
                            "fillcolor": "white",
                            "pencolor":"#228be6",
                            "fontcolor": "#228be6" ,
                            "fontname": "Helvetica-Bold",
                            "penwidth": "2",
                            "fontsize": "14"
                            }

_az_graph_attr = {"style": "filled", 
        "fillcolor": "#e7f5ff",
        "style": "filled, dotted",
        "penwidth": "2"
        }

diagram_graph_attr ={
         "labelloc": "t",         
        "fontsize": "30",    
        "fontname": "Helvetica-Bold",
        "splines": "curved",
        "nodesep": "1.5",
        "ranksep": "1.2"
    }

with Diagram("AWS Three Tier Web Architecture Workshop",
             show=False, 
             filename="aws_full",
             outformat="png",
             graph_attr=diagram_graph_attr):


    with Cluster( graph_attr={"label":"VPC",
                              "fontsize": "20",
                              "style": "filled", 
                              "fillcolor": "#ebfbee",
                              "penwidth": "2",
                              "pencolor":"#000000"
                              }):

        # Internet Gateway y ELB Web (externo)
        igw = InternetGateway("Internet \nGateway")
        elb_web = ELB("ELB Web")
        elb_app = ELB("ELB App")

        # ---------------- Web Tier ----------------
        with Cluster("Web Tier", graph_attr=_cluster_layers_graph_attr):
            with Cluster("AZ1", graph_attr=_az_graph_attr):
               with Cluster("Public Subnet", graph_attr= _public_subnet_graph_attr):
                  ec2_web_az1 = EC2("Web EC2")
            with Cluster("AZ2", graph_attr=_az_graph_attr):
              with Cluster("Public Subnet", graph_attr=_public_subnet_graph_attr):
                  ec2_web_az2 = EC2("Web EC2")

        igw >> elb_web
        elb_web >> [ec2_web_az1, ec2_web_az2]
        ec2_web_az1 >> elb_app
        ec2_web_az2 >> elb_app

        # ---------------- App Tier ----------------
        with Cluster("App Tier", graph_attr=_cluster_layers_graph_attr,direction='TB'):
            with Cluster("AZ1", graph_attr=_az_graph_attr):
              with Cluster("Private Subnet", graph_attr=_private_subnet_graph_attr):
                ec2_app_az1 = EC2("App EC2")
            with Cluster("AZ2", graph_attr=_az_graph_attr):
              with Cluster("Private Subnet", graph_attr=_private_subnet_graph_attr):
                ec2_app_az2 = EC2("App EC2")

        elb_app >> [ec2_app_az1, ec2_app_az2]

        # ---------------- Database Tier ----------------
        with Cluster("Database Tier", graph_attr=_cluster_layers_graph_attr,direction='TB'):
            with Cluster("AZ1", graph_attr=_az_graph_attr):
                with Cluster("Private Subnet", graph_attr=_private_subnet_graph_attr):
                  aurora_primary = Aurora("Aurora Primary \nDB")
            with Cluster("AZ2", graph_attr=_az_graph_attr):
              with Cluster("Private Subnet", graph_attr=_private_subnet_graph_attr):
                  aurora_readreplica = Aurora("Aurora Read \nReplica") # 

            ec2_app_az1 >> aurora_primary
            ec2_app_az2 >> aurora_primary

Image("aws_full.png")
Enter fullscreen mode Exit fullscreen mode

3. Output Diagram

Image description


📂 GitHub Repository

All code used in this tutorial is available here:

GitHub logo r0mymendez / doc-as-diagrams-aws-architecture

A practical example of how to use Diagram-as-Code in Python to recreate an AWS architecture diagram with customizable styling and version-controlled documentation.

Buy Me A Coffee


You Asked, I Coded: AWS Architecture as Diagram-as-Code

A few days ago, someone left a comment on my previous article — a post that turned out to be very popular, reaching over 50K views and earning 300 GitHub stars ⭐️ ❤️ I want to sincerely thank every single reader who took the time to read, leave feedback, and star the repository Your support truly motivates me to keep writing, sharing, and growing with the community.

Image description


🙃 A Reader’s Question That Inspired This Post

👤 @reader
📅 May 2, 2025
Hey Romina, would you please make this diagram using Diagram as Code?

🔗 Link to the original diagram

👍 1  💬 1 replies  Reply

Haven’t read my first article?

If you’re new to Diagram-as-Code, I highly recommend starting with my introductory tutorial.

Link to the article

img-diagram


What is Diagram-as-Code?

Let’s go over a quick introduction to Diagram-as-Code.

Diagram-as-Code is an…

If you find it useful, feel free to leave a ⭐️ and follow me — it helps me continue sharing free technical content with the community!


Final Conclusions

Using Diagram-as-Code is an effective approach for maintaining architecture diagrams in a consistent, automated, and version-controlled manner. However, it is essential to recognize both its limitations and its advantages.

❌ Limitations

  1. Accurately replicating a visual design can be difficult. The library does not natively support complex layouts, such as a node appearing in multiple clusters, and managing deeply nested clusters can quickly become cumbersome

✅ Benefits

  1. Despite these challenges, Diagrams remains a valuable tool for defining infrastructure visually through code.

  2. It allows seamless version control of visual documentation alongside the project’s source code.

  3. Teams can track architectural changes over time, providing transparency and traceability.

  4. It enables the automation of documentation pipelines, particularly beneficial in DevOps and cloud-native environments.

  5. When integrated with AI-powered tools, this approach offers exciting opportunities — from enabling agents to query diagrams, to automatically generating changelogs and visualizing the evolution of an architecture over time.


📚 References

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (1)

Collapse
 
madhurima_rawat profile image
Madhurima Rawat

This looks amazing! You're incredibly talented at replicating such complex diagrams! 🎯

Bump.sh

Hate writing docs?

Hate undocumented APIs even more?

Bump.sh generates an always up-to-date API reference site for REST and Event-Driven Architectures.

Plug it in your CI. It fetches your OpenAPI and AsyncAPI (GraphQL pending) spec files, and even generates a diff. Gather all of your API docs in a single source of truth.

Try it for free