Master this essential documentation concept
A modern text-based diagramming language designed to produce clean, polished architecture and infrastructure diagrams from plain text definitions stored in code repositories.
A modern text-based diagramming language designed to produce clean, polished architecture and infrastructure diagrams from plain text definitions stored in code repositories.
When your team adopts D2 as your diagramming standard, the learning curve often plays out in recorded sessions — architecture walkthroughs, onboarding calls, or live coding demonstrations where someone shares their screen and explains how to structure a D2 file to represent a microservices topology or a CI/CD pipeline.
The problem is that D2 syntax, conventions, and your team's specific diagramming patterns get buried inside those recordings. A new engineer trying to understand why your team uses a particular D2 layout for network diagrams has to scrub through a 45-minute meeting to find a two-minute explanation. There's no way to search for "D2 connection syntax" or "how we label external services" across your video library.
Converting those recordings into structured documentation changes this entirely. Imagine a walkthrough where a senior architect explains your D2 conventions getting transformed into a searchable reference — complete with the actual D2 code snippets discussed, the reasoning behind naming decisions, and step-by-step guidance your whole team can find in seconds. Your D2 standards stop living in someone's recorded screen share and start becoming a living part of your documentation system.
If your team regularly explains technical tooling like D2 through meetings and demos, there's a more efficient way to preserve that knowledge.
Engineering teams maintain architecture diagrams in Lucidchart or draw.io, but these binary files cannot be meaningfully reviewed in pull requests. When a new service is added or a dependency changes, the diagram is either forgotten or updated manually weeks later, causing documentation drift that misleads new engineers during onboarding.
D2 stores architecture definitions as plain .d2 text files committed alongside service code. Reviewers can diff diagram changes in GitHub pull requests exactly like code, and CI pipelines automatically re-render SVGs on merge, ensuring the published diagram always reflects the current state of the repository.
['Create an `architecture/services.d2` file in the monorepo root defining each microservice as a node and inter-service API calls as directed edges with labels like `REST /orders` or `gRPC stream`.', 'Add a GitHub Actions step that runs `d2 architecture/services.d2 docs/architecture.svg` on every push to main, committing the rendered SVG back to the docs folder.', "Enforce a PR checklist item: 'If a new service or dependency was added, update services.d2.' Reviewers can see the textual diff and catch missing connections before merge.", "Embed the rendered SVG in the team's README.md using a relative image link so it is always current when developers clone the repository."]
Architecture diagrams stay accurate within one pull request cycle of any infrastructure change, and new engineers can trace service dependencies by reading a single versioned file rather than hunting through stale wiki pages.
Platform teams document AWS infrastructure separately for dev, staging, and production environments. Maintaining three nearly identical Visio files leads to copy-paste errors where production diagrams show outdated VPC CIDR ranges or missing NAT gateways, creating confusion during incident response.
D2 supports variables and imports, allowing teams to define a base infrastructure topology once and override environment-specific values such as instance types, replica counts, and CIDR blocks using D2's `vars` block. A single `make diagrams` command renders all three environment diagrams from one canonical source.
['Write a `base-infra.d2` file defining the logical topology: VPC, public and private subnets, ALB, ECS cluster, RDS primary, and read replica nodes with connection labels.', 'Create `prod.d2`, `staging.d2`, and `dev.d2` files that import `base-infra.d2` and override vars like `db_instance: db.r6g.2xlarge` for prod versus `db.t3.medium` for dev.', 'Add a Makefile target that loops over the three environment files and runs `d2 --theme 200 {env}.d2 docs/infra/{env}.svg` to produce themed, labeled SVGs.', "Link each environment's SVG in the runbook for that environment so on-call engineers see an accurate diagram without navigating to a separate tool."]
Three accurate, visually consistent environment diagrams are produced from a single source of truth, eliminating the class of incidents where engineers apply a fix to the wrong tier because they misread an outdated diagram.
API platform teams struggle to explain multi-step authentication and routing flows to external developers. Prose descriptions of OAuth token exchange, rate limiting middleware, and backend fan-out are long and error-prone, yet sequence diagrams in tools like Miro require design tool access and cannot be updated by backend engineers who only work in code editors.
D2's sequence diagram syntax lets backend engineers write request flow diagrams as text directly in the API documentation repository. The clean rendered output with D2's built-in sketch or terminal themes is embedded in the developer portal, and any engineer can submit a PR to correct a step without learning a GUI tool.
['Create `docs/flows/oauth-token-exchange.d2` using D2 sequence diagram blocks to model the client, API gateway, identity provider, and backend service as actors with labeled arrows for each HTTP call and response.', 'Use D2 `note` blocks to annotate critical steps such as token TTL validation and the 401 retry loop, making the diagram self-documenting without requiring a separate explanation paragraph.', 'Run `d2 --layout elk docs/flows/oauth-token-exchange.d2 portal/static/oauth-flow.svg` in the documentation build pipeline triggered on every docs branch merge.', "Reference the SVG in the OpenAPI specification's `x-readme` extension or embed it in the developer portal's Getting Started page with a link to the source .d2 file in GitHub."]
External developer support tickets related to authentication flow misunderstandings drop measurably, and the average time for a new API consumer to successfully complete OAuth integration decreases because the sequence diagram precisely mirrors the actual gateway behavior.
Architecture Decision Records (ADRs) written in Markdown often reference diagrams that are stored as binary image attachments or external Lucidchart links. Over months, the external links rot, the images become orphaned, and the context needed to understand why a technology was chosen is lost, making ADRs unreliable as historical references.
D2 diagram source is embedded or co-located with each ADR as a plain text .d2 file. Because the diagram definition is human-readable text, it can be read and understood even if the rendering toolchain changes, and it is indexed by code search tools like GitHub's search or Sourcegraph, making ADRs discoverable by component name.
["Establish a convention where each ADR directory contains both `decision.md` and `context-diagram.d2`, with the .d2 file showing the architectural options considered and the chosen path highlighted using D2's `style` block with a distinct fill color.", 'Add a `d2` render step to the documentation CI job that processes all `*.d2` files under the `docs/adr/` directory and writes SVGs adjacent to each decision file.', 'Update the ADR template to include a `## Context Diagram` section with a relative Markdown image link to the rendered SVG, so the diagram appears inline when browsing the repository on GitHub.', 'Configure Sourcegraph or GitHub code search to index .d2 files, enabling engineers to search for a service name like `PaymentService` and find every ADR that references it in a diagram.']
ADRs remain self-contained and fully renderable years after creation. Engineers performing system audits or planning migrations can find all architectural decisions involving a specific component through a single code search query, reducing research time from hours to minutes.
Placing `architecture.d2` or `data-flow.d2` files in the same directory as the service or module they document creates an implicit ownership contract. When a developer changes a service's API surface, the adjacent diagram file is a natural reminder to update the documentation. This co-location strategy also ensures diagrams are included in code reviews without requiring a separate documentation PR.
D2 edges support rich label syntax, allowing you to annotate connections with the protocol, HTTP method, event topic name, or data format rather than leaving relationships unlabeled. Labeled edges turn a topology diagram into a communication contract reference that engineers can consult during debugging or integration work. This information is especially valuable in microservices diagrams where implicit coupling is a common source of production incidents.
D2 is actively developed and new releases occasionally change default layout behavior, font rendering, or theme output. If your CI pipeline installs the latest D2 version on every run, a new release can silently change the visual output of your diagrams, causing SVGs embedded in documentation to look different without any corresponding change in the .d2 source file. Pinning the version ensures reproducible renders across all environments.
D2 ships with numbered themes (0 through 300+) and supports custom theme overrides via the `--theme` CLI flag or inline `vars` blocks. Using different themes across diagrams in the same documentation site creates a fragmented visual experience that signals low documentation quality to readers. Selecting one theme for light mode and one for dark mode and applying them uniformly through a Makefile or CI variable ensures visual cohesion.
D2 supports nested containers using curly brace syntax, allowing you to group nodes that belong to the same AWS VPC, Kubernetes namespace, or bounded domain context. Grouping reduces the number of visual elements readers must parse simultaneously and makes the diagram's logical boundaries explicit without requiring additional prose explanation. Containers also enable D2's layout engine to optimize spacing within and between groups independently.
Join thousands of teams creating outstanding documentation
Start Free Trial