The views expressed on this website are mine alone and do not necessarily reflect the views of my employer.

Don't dread diagrams with D2 Lang

White puzzle pieces scattered on a table

Photo by Markus Winkler on Unsplash


I recently started as a lead on a project and received some D2 code that represented the proposed architecture. I was a little confused. Why not use one of the many other tools? I learned that a diagram written in D2 can be quick to implement while also being easy to pickup because of its intuitive syntax.

What is D2?

A modern language that turns text to diagrams. Create beautiful diagrams in minutes. Simple syntax. Endlessly customizable. D2 is the fastest and easiest way to get a mental model from your head onto the screen, then make edits with your team.

- D2 Website

A diagram showing how an add to cart action will communcate between services

Here is an example of what a simple d2 diagram can look like for a add to cart flow on a website

# Shapes

user {
    label: User
}

website {
    label: myshop.com
}

apiGateway {
  label: API Gateway
}

cloud {
    label: Cluster

    auth  {
        label: Authentication Service
        validate: {
          label: /Validate
        }
    }
    products {
        label: Products Service
        getProducts: {
          label: /AddItemsToCart
        }
    }
}


# Connections

user -> website: 1. Adds Items to Cart
website -> apiGateway: 2. Product Data
apiGateway <-> cloud.auth.validate: 3. Checks Session
apiGateway -> cloud.products.getProducts: 4. Product Data

Generally the language reads really well, but we will break up this file into Shapes and Connections.

Shapes

Shapes generally make up anything that isn't a line connecting two things. Some examples are "User", "myshop.com", "API Gateway"

Here is how we define the website Shape.

website {
    label: myshop.com
}

website is the variable we will use to reference this when we make a connection. We can add a "label" to a shape to make the diagram clearer. If you don't provide one, it will default to the variable name

Shape's shape

There are other keywords you can use to visually change a Shape. One useful one is the shape keyword. You can change the shape of your Shape with it.

Given this code, it will change the shape to a page

website {
    label: myshop.com
    shape: page
}
A page icon with 'myshop.com' in the middle

Containers

If you define something within the curly braces it will be "contained" by the parent.

Check out this cloud example. We know that label is a keyword, so that won't be a Shape. auth probably isn't a keyword so that will be another Shape, but auth also has more shapes in it 🤯. In this example, there is a container for any relevant endpoints within the auth service.

cloud {
    label: Cluster

    auth  {
        label: Authentication Service
        validate:{
          label: /Validate
        }
    }
    products {
        label: Products Service
        getProducts: {
          label: /AddItemsToCart
        }
    }
}

Connections

The last thing to cover are connections. How do these different shapes and containers interact? Connections can represent user actions, network calls, etc.

To define a connection you use a shape and then use arrows to connect them. You can add a label to a connection by using a : then the label.

user -> website: 1. Adds Items to Cart
website -> apiGateway: 2. Product Data
apiGateway <-> cloud.auth.validate: 3. Checks Session
apiGateway -> cloud.products.getProducts: 4. Product Data

Single arrows that look like -> are one way connections where two way arrows that looks like <-> represnt two way connections. Easy! There is a lot more that you can do with connections like

  • Changing Arrow shapes
  • Arrow labels
  • Cyclic Connections
  • Chaining Shapes

Beyond Simple diagrams

Diagrams can get pretty complex! We've seen that D2 can do node and edge type diagrams, like we just saw, but it also supports

Why you should considor D2 Lang

Prototyping a diagram can happen very quickly with D2. A lot of times when creating a diagram with drag/drop or drawing solutions, it can take a while to get a good looking diagram. Even after you get things just right, someone will add in a new thing and you will need to shift everything around to make it look good again. With D2 it's easy to add shapes and connections and then let D2 figure how to balance the diagram.

If your company is tied to a specific diagraming tool, it can be easy to transfer the design to your company's diagraming tool.

If your company doesn't have an official tool, this can be a good time to suggest D2. It has a few advantages over other tools.

  1. It's free!
  2. Because D2 is a programming language it can be version controlled.
    • Commit diagrams alongside the code they represent
    • Track changes to architecture over time
    • Use a build tool, like lefthook, to generate images for docs at commit time