Optimising a pipeline
Optimize a pipeline for cost, time, performance, and reliability
Measure, change, verify
Baseline pipeline-duration percentiles, per-task duration, and queued/running-job pressure. Identify the measured constraint, change one lever, then compare duration, failures, queueing, and cost/quota consumption. Repeat rather than stacking unmeasured changes.
The levers
| Lever | Effect |
|---|---|
| Caching | Accelerate cross-run regeneration; cache absence must not make the job fail |
| Parallelism | Split independent work across jobs when dependencies, agents, and capacity allow |
| Path filters | Do not build at all for documentation-only commits |
| Matrix | One definition, many legs, throttled by maxParallel |
| Pipeline artifacts | Carry required outputs between jobs; unlike a cache, their absence is a failure |
| Agent choice | Balance clean/stateless isolation against deliberate state reuse and ownership |
Caching and the key
A Cache@2 primary key can combine stable tool/OS discriminators with a lockfile path; the task hashes the file contents. Caches are immutable. A fixed overbroad key can retain outdated contents, while an overspecific primary key reduces exact-hit reuse. restoreKeys can return a partial hit when the exact key misses, so a commit SHA defeats cross-commit exact reuse but not every possible fallback hit.
- task: Cache@2
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(Pipeline.Workspace)/.npmMeasure restore/save overhead and test the cache-miss path. Use a pipeline artifact—not a cache—for files a downstream job requires.
Capacity, agents, and cost
Azure DevOps YAML jobs run in parallel by default only when no dependency blocks them and agents plus organization-level parallel-job capacity are available. Declare dependsOn for required ordering and bound matrix fan-out with maxParallel.
Private projects can use a monthly-limited Microsoft-hosted free tier or paid parallel-job capacity with no monthly limit. Self-hosted capacity is also licensed by concurrent jobs, while its machines, patching, and isolation remain your responsibility. Microsoft-hosted pools supply a clean VM. Managed DevOps Pools add a managed choice: stateless supplies a fresh agent for each job; stateful reuse can preserve files/packages but needs an explicit security and cost decision. Benchmark VM size, storage, region, standby, and state instead of assuming bigger or warmer is better.
Primary sources
- https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/az-400
- https://learn.microsoft.com/en-us/azure/devops/report/powerbi/sample-pipelines-duration
- https://learn.microsoft.com/en-us/azure/devops/report/powerbi/sample-pipelines-task-duration-trend
- https://learn.microsoft.com/en-us/azure/devops/pipelines/release/caching
- https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/trigger
- https://learn.microsoft.com/en-us/azure/devops/pipelines/process/phases
- https://learn.microsoft.com/en-us/azure/devops/pipelines/licensing/concurrent-jobs
- https://learn.microsoft.com/en-us/azure/devops/managed-devops-pools/manage-costs
- https://learn.microsoft.com/en-us/azure/devops/managed-devops-pools/configure-scaling
- https://learn.microsoft.com/en-us/azure/devops/pipelines/security/misc