skip to content

In Azure DevOps, when during a YAML pipeline run are the approvals and checks on a protected resource evaluated, and what is the run doing while they are pending?

level: seniorimportance: must knowfreq 60%

answer

  1. the gate sits in front of a whole stage
  2. nothing is queued while it waits
  3. the union of every resource used
  4. all of them, never any of them
  5. some checks ask again later

basics

~20 s

Checks are evaluated at the start of any stage that consumes the protected resource. The stage queues no jobs and holds no agent while it waits; every check on every resource the stage uses must pass before any job starts.

solid answer

~50 s

Azure DevOps evaluates checks per **stage**, not per job or per step. When a stage references a protected resource — an environment, service connection, agent pool, repository, variable group or secure file — the run pauses at the beginning of that stage. All checks on *all* protected resources the stage touches are gathered and evaluated together, and they must **all** pass; there is no partial start. No agent is consumed while waiting, so a pipeline sitting on an approval for two days costs no parallel job slot. Human approvals wait for a person, up to their configured timeout of at most 30 days. Automated checks such as **Business Hours**, **Invoke REST API** or **Invoke Azure Function** can re-evaluate on a configured interval until they pass or the timeout expires. On timeout the stage never runs. Because two deployment jobs in one stage share the environment, approvers are prompted once.

go deeper

for a junior

Know that a run pauses before a gated stage and that someone must approve it in the Azure DevOps run view before any of that stage's jobs start.

for a middle

Explain that the gate is per stage, that the checks from every protected resource the stage uses are combined, and that all of them must pass before a single job is queued.

for a senior

Demonstrate operational reading: no agent is held while waiting, automated checks can re-evaluate on an interval until timeout, and callback-mode REST checks are how an external change system reports its verdict.

for a principal

Shape the stage boundaries deliberately, since each gated stage is another human interruption. Decide which controls are automated checks and which genuinely need a person, and make sure a parked queue plus an exclusive lock cannot release into an unreviewed pile-up.

## The unit of gating is the stage This is the single fact that most candidates get wrong, and it explains several behaviours that otherwise look like bugs. Azure DevOps does not gate a job or a step — it gates a **stage**. When a run reaches a stage that uses a protected resource, the stage enters a waiting state before any job is queued. Consequences worth stating out loud: - Two deployment jobs in the same stage targeting the same environment produce **one** approval request, not two. - Splitting a deployment into more jobs does not multiply approvals, but splitting it into more *stages* does. - A stage that uses an environment *and* a production service connection *and* a restricted variable group waits for the union of all their checks. ## What counts as a protected resource Checks attach to environments, service connections, agent pools, repositories declared as `resources: repositories`, variable groups and secure files. It is the resource that carries the gate, not the YAML. A pipeline author editing the file cannot remove a check, which is precisely the property compliance teams are buying. ## Everything must pass, and it is an AND The checks a stage must satisfy are the union across every protected resource it consumes, and the relationship is conjunctive. There is no "any one of these" mode. Where checks differ is in *how* they wait: - **Approvals** block on a human. Configurable settings include the minimum number of approvers, whether approvers may approve in any order or must go sequentially, whether the person who queued the run may approve it, and an instruction string shown to approvers. The timeout is at most 30 days. - **Branch control** verifies the run is from an allowed branch, and can additionally require that the branch has protection configured, failing closed when protection state cannot be determined. - **Business hours** only passes inside a configured window and time zone, so an out-of-hours run parks until the window opens rather than failing. - **Invoke REST API** and **Invoke Azure Function** call out to your own system. They run in one of two completion modes: the check succeeds based on parsing the immediate response against a success criteria expression, or it stays pending until your service calls back into Azure DevOps to report the result. Callback mode is what a change-management system uses when a human process takes hours. - **Exclusive lock** admits one run at a time to the resource. `lockBehavior` decides what happens to the queue: `sequential` runs the waiting runs in order, `runLatest` keeps only the newest and cancels the rest. - **Evaluate artifact** applies a policy to the artifact's metadata before it may be deployed. - **Required template** passes only if the pipeline extends from a template you nominated, so a pipeline cannot reach the resource without inheriting your mandated steps. ## Re-evaluation and timeout Automated checks have a **time between evaluations** setting. Set to zero, the check runs once and its verdict stands. Set to a non-zero interval, the check re-runs on that cadence until it passes or its timeout expires — which is how a business-hours check parks a Friday-evening run until Monday, and how a REST check polls a change ticket until it is approved. When a timeout expires, the stage does not run. ## No agent is held Waiting is free in the dimension that usually matters. The stage has not queued jobs, so no parallel job slot and no self-hosted agent are tied up. A pipeline sitting on an approval overnight is not consuming capacity. What it *does* consume is a lease on your deployment order: a run parked in front of production still holds its place, so several parked runs plus an exclusive lock can produce a surprising pile-up when approvals finally land. ## Diagnosing the common confusions "Why did nobody get an approval request?" — usually the environment that was actually referenced is not the one carrying the checks, because a mistyped name auto-created a new, ungated environment. "Why did it deploy before the check passed?" — usually the deploying step is in a different stage than the one holding the protected resource, so the gated stage was not the stage doing the work. "Why are we being asked twice?" — the deployment was split across two stages, each consuming the environment.

  • A stage uses both a gated environment and a gated production service connection. What does the run wait for?
    Both. Azure DevOps collects the checks from every protected resource the stage consumes and requires all of them to pass — it is a conjunction with no partial start. That is why an unexpected approval prompt often traces back to a service connection or variable group nobody remembered was protected, rather than to the environment.
  • How does an Invoke REST API check handle an external process that takes hours?
    Use its callback completion mode. The check goes pending immediately, and your service later calls back into Azure DevOps with the verdict, which is how a change-management system reports a ticket approval. If the callback never arrives before the configured timeout, the check fails and the stage does not run — so the external system needs its own reliability story.
  • Does a pipeline waiting a day on an approval consume a parallel job slot?
    No. The stage has not queued any jobs, so no hosted parallel job and no self-hosted agent is held. What it does hold is its position in the deployment order: several parked runs behind an exclusive lock can release into a pile-up once approvals land, which is worth planning for.

saying these in an interview costs you the question

  • Saying checks are evaluated per job or per step
  • Assuming an agent sits idle during an approval
  • Thinking any one passing check releases the stage
  • Believing checks are declared in the pipeline YAML
  • Expecting an approval prompt per deployment job in a stage

context