CI/CD Diagram Guide

Azure DevOps pipeline diagram: stages, environments, and the checks nobody draws

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

Azure Pipelines gives you four nouns and most diagrams collapse them into one. A stage is a boundary, a job is a unit of work on an agent, a deployment job is a job that targets an environment and carries a strategy, and an environment is a first-class resource that owns its own approvals and checks. Draw those four correctly and the diagram answers the questions people actually bring to it, starting with who can send a build to production.

7 min readFor teams running multi-stage YAML pipelines in Azure DevOps

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

217/20003 credits left
Try:

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 node

Templates 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

Approvals and checks live on environments, service connections, repositories, variable groups, secure files, and agent pools, never in the pipeline file. A diagram that shows them is strictly more informative than the source it was drawn from, which is unusual and worth the annotation effort.

FAQ

How do I diagram an Azure DevOps multi-stage YAML pipeline?

Draw stages as columns wired by dependsOn, jobs as nodes inside them with their agent pool when it is not the default, deployment jobs annotated with their strategy such as runOnce, rolling, or canary, and environments as zones the deployment jobs target. Approvals and checks belong on the environment zones because that is where they are configured.

Where do approvals appear in an Azure Pipelines diagram?

On the environment, not in the stage sequence. Static checks (branch control, required template, evaluate artifact) and dynamic checks (approval, invoke Azure Function, invoke REST API, business hours, query Azure Monitor alerts) are configured on the resource in project settings, so they are absent from the YAML. Note the approver group, the timeout, and whether self-approval is permitted on the environment zone.

What is the difference between a job and a deployment job on the diagram?

A job runs steps on an agent and has no environment. A deployment job targets a named environment, records deployment history against it, and declares a strategy that controls how the rollout happens. Give deployment jobs a distinct shape and write the strategy on them, since a canary strategy and a runOnce strategy represent very different risk postures.

How do I handle a pipeline that uses extends and templates?

Resolve the composition before drawing. A pipeline that extends a platform template can gain entire stages and injected steps that the consuming repository cannot remove, so diagramming the consumer file alone omits real columns. Draw steps injected identically across jobs once as a stage annotation rather than repeating them in every job node.

How do I show a classic release pipeline alongside YAML?

As two zones joined by the artifact. The YAML pipeline publishes a pipeline artifact, the classic release consumes it through an artifact source with a trigger, and the release stages carry their own pre-deployment and post-deployment approvals and gates. Naming the artifact on the connecting arrow makes the handoff and any migration plan much easier to discuss.