See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Four nouns to get right before placing a single shape
A stage groups jobs and is the unit that dependsOn wires together, so stages are the columns of the diagram. A job runs on an agent from a pool and is the unit that decides where work executes, so pool and demands belong on the job node when they differ from the default.
A deployment job is the important one. It targets an environment, it records deployment history against that environment, and it carries a strategy such as runOnce, rolling, or canary. That strategy is architectural information: a canary deployment job with a preDeploy and a routeTraffic phase is a different risk posture from a runOnce, and the diagram should say which one it is.
An environment is not a stage. It is a named resource in the project that can hold Kubernetes namespaces or virtual machine resources, and, critically, it is where approvals and checks are configured. Two stages can deploy to the same environment, and one stage can deploy to several. Drawing environments as zones rather than as boxes in the stage row keeps that relationship legible.
Approvals and checks live on the environment, so draw them there
The most common mistake in an Azure Pipelines diagram is drawing an approval as a step inside the pipeline. It is not in the YAML at all. Microsoft splits these into static checks, which are branch control, required template, and evaluate artifact, and dynamic checks, which are approval, invoke Azure Function, invoke REST API, business hours, and query Azure Monitor alerts. They are configured on the resource, and the resource can be an environment, a service connection, a repository, a variable group, a secure file, or an agent pool. That is already more surfaces than most diagrams account for.
That has a consequence worth drawing: the pipeline file alone cannot tell you whether production is gated. A reviewer reading the YAML sees a deployment job and no approval, and concludes wrongly. Put the checks on the environment zone with their configuration summarised: approvers, timeout, whether the requester may self-approve, and which automated checks run before the approval is even offered.
Automated checks deserve their own small shapes when they can block. An Azure Monitor alert check that queries for active alerts before allowing promotion is functionally a quality gate, and a reader who does not see it on the diagram will not know the promotion can be blocked by a monitoring signal.
Two behaviours belong on the zone label because they surprise people. Checks within a category run in parallel, categories run one after another, and a failed category stops the ones behind it, so a branch control check can mean the approval is never offered at all. And an approval defaults to a 30 day timeout, allows up to 365 days, and marks the stage skipped rather than failed when it expires, which is a green run that never deployed.
# azure-pipelines.yml, trimmed to what the diagram shows
extends:
template: templates/pipeline.yml@platform # the config you are not reading
stages:
- stage: Build # column 1
jobs:
- job: compile
pool: { vmImage: ubuntu-latest }
- stage: DeployStaging # column 2
dependsOn: Build
jobs:
- deployment: staging # deployment job, not a plain job
environment: staging # zone; approvals configured on the resource
strategy: { runOnce: { deploy: { steps: [] } } }
- stage: DeployProd # column 3
dependsOn: DeployStaging
condition: succeeded()
jobs:
- deployment: prod
environment: production # approvals + branch control live here
strategy:
canary: { increments: [10, 50] } # risk posture, put it on the nodeTemplates and extends: the half of the pipeline not in your file
A pipeline that begins with extends is not the pipeline. The platform template it extends can add stages, inject steps into every job, and enforce required checks that the consuming repository cannot remove. Diagramming the consumer file alone produces a picture that is missing whole columns.
Resolve the composition first. List every template reference, including template expressions with parameters and templates pulled from another repository through a repository resource, and decide which of them contribute shapes. Injected steps that are identical across jobs, such as a credential scan, are better drawn once as an annotation on the stage than repeated in every job node.
Variable groups from the library are the other silent input. A deployment job whose target subscription comes from a variable group looks environment-agnostic in the YAML and is not. Annotate the environment zone with the variable group and service connection it uses, since that pair is what a reviewer needs in order to check separation of duties.
Classic release pipelines on the same page
Plenty of organisations run both: YAML pipelines for build and a classic release pipeline for deployment, often because the classic release UI held the approval configuration first. Drawing only the YAML half in that situation documents the least interesting part of the process.
Represent the handoff explicitly. The YAML pipeline publishes a pipeline artifact, the classic release consumes it as an artifact source with a trigger, and the release stages carry their own pre-deployment and post-deployment approvals and gates. Two zones and one arrow between them, with the artifact named, makes a migration conversation much shorter.
When the diagram lives in an Azure DevOps wiki, publish it as an embed rather than an attachment so the page follows the canvas. The mechanics are covered in embedding diagrams in an Azure DevOps wiki.
The YAML does not contain the gate
FAQ
How do I diagram an Azure DevOps multi-stage YAML pipeline?
Where do approvals appear in an Azure Pipelines diagram?
What is the difference between a job and a deployment job on the diagram?
How do I handle a pipeline that uses extends and templates?
How do I show a classic release pipeline alongside YAML?