Many platform teams store templates in a central repo and reference them as pipeline resources. That way dozens of application repos consume the same delivery framework.
Templates & Reuse
Scale Azure DevOps YAML by extracting repeated logic into step, job, stage, and variable templates so many teams can share one delivery standard without copying the same pipeline everywhere.
🧒 Simple Explanation (ELI5)
If every team writes its own copy of the same recipe, eventually one copy says bake for 10 minutes, another says 12, another forgets salt, and nobody knows which one is correct. Templates solve that problem. You keep one trusted recipe and let teams fill in only the parts that change.
🔧 Technical Explanation
Why Templates Matter
- Reduce copy-paste across repositories.
- Standardize testing, security scanning, and deployment behavior.
- Make platform improvements available to many teams from one place.
- Support safer governance because shared patterns are easier to audit.
| Template Type | Best For | Example |
|---|---|---|
| Step template | Small repeated command sequences | Install tools, authenticate registry |
| Job template | Standard jobs | Build .NET service, run security scan |
| Stage template | Environment promotion logic | Reusable AKS deploy stage |
| Variable template | Shared config data | Default image name, chart path |
Parameterized Job Template
# templates/jobs/docker-build.yml
parameters:
- name: imageRepository
type: string
- name: dockerfile
type: string
default: Dockerfile
jobs:
- job: BuildImage
pool:
vmImage: ubuntu-latest
steps:
- task: Docker@2
inputs:
command: buildAndPush
repository: ${{ parameters.imageRepository }}
dockerfile: ${{ parameters.dockerfile }}
containerRegistry: 'sc-acr-shared'
tags: '$(Build.BuildId)'Using the Template
stages:
- stage: Build
jobs:
- template: templates/jobs/docker-build.yml
parameters:
imageRepository: 'payments-api'
dockerfile: 'src/Payments/Dockerfile'Reusable AKS Deploy Stage
# templates/stages/aks-deploy.yml
parameters:
- name: environmentName
type: string
- name: namespace
type: string
stages:
- stage: Deploy_${{ parameters.environmentName }}
jobs:
- deployment: Deploy_${{ parameters.environmentName }}
environment: ${{ parameters.environmentName }}
strategy:
runOnce:
deploy:
steps:
- script: |
helm upgrade --install webapp ./charts/webapp \
--namespace ${{ parameters.namespace }} \
--set image.tag=$(Build.BuildId)This pattern keeps AKS promotion consistent without repeating the same deployment logic across every repository.
🛠️ Hands-on
Refactor Copy-Pasted Pipeline Logic
- Find repeated jobs like test, Docker build, Helm deploy, or security scan.
- Extract them into templates with a small parameter surface.
- Keep behavior opinionated. Do not create templates with 40 switches.
- Version and review template changes carefully because many pipelines may depend on them.
Variable Template Example
# templates/vars/common.yml variables: chartPath: 'charts/webapp' acrLoginServer: 'contosoregistry.azurecr.io' kubernetesNamespace: 'default' # usage variables: - template: templates/vars/common.yml
🐛 Debugging Scenarios
Scenario 1: Template Not Found
- Check relative path from the calling pipeline file.
- Validate repository resource alias if templates live in another repo.
- Confirm the branch or ref for the template repository is correct.
Scenario 2: Parameter Is Empty Unexpectedly
- Verify compile-time vs runtime syntax. Template parameters use
${{ }}. - Check the parameter name exactly matches the template definition.
- Confirm a default value exists where appropriate.
Scenario 3: Template Change Breaks Many Pipelines
- Version templates or test changes in a lower-risk branch first.
- Use a consumer test pipeline to validate shared templates before broad rollout.
- Avoid backward-incompatible parameter changes without a migration plan.
The goal is reuse, not cleverness. If nobody can read the pipeline after templating, you traded duplication for fragility.
📋 Interview Questions
Beginner
To avoid duplication, standardize behavior, and make pipeline logic easier to reuse across repositories and teams.
Step, job, stage, and variable templates.
They let a shared template stay generic while consumers provide the small set of values that differ, such as environment or image name.
Yes. Azure Pipelines can reference templates from external repositories using resources.
Because changes become slow, inconsistent, and difficult to govern when every repository has its own slightly different version.
Intermediate
Keep templates opinionated with a small, clear parameter surface. Too much configurability usually recreates the complexity you were trying to remove.
When one central change impacts many pipelines without testing, when parameter sprawl makes behavior unclear, or when nobody owns template versioning.
They encode safe defaults and standard steps such as scanning, artifact naming, and deployment patterns so teams inherit consistent controls automatically.
You can centralize Helm deploy stages, shared Azure authentication, and common rollout logic so every AKS-bound service follows the same delivery model.
A variable template is YAML stored in Git and reviewed like code. A variable group is managed in Azure DevOps Library and often better for shared operational configuration and secrets integration.
Scenario-Based
I identify the last known-good template version, roll back or pin affected consumers, then add validation pipelines and versioning so future shared changes are tested before broad rollout.
I standardize the critical platform behaviors such as build, scan, and deploy controls, then expose a small number of parameters so teams can handle legitimate service differences without breaking consistency.
Yes, if many services share the same AKS delivery pattern. Centralization improves reliability and governance, as long as the template has clear ownership and compatibility management.
Azure DevOps builds the final pipeline structure first by expanding templates and parameters, and only then runs the actual jobs. That is why template parameters use compile-time syntax.
If the logic is truly unique, still changing rapidly, or would require so many conditional branches that the template becomes harder to reason about than duplicated code.
🌍 Real-World Usage
Large Azure DevOps estates depend on templates to keep hundreds of pipelines aligned. Shared build, security, and AKS deployment patterns give teams a paved road while still allowing application-specific inputs where needed.
🧾 Summary
Templates are how Azure Pipelines scale. They turn YAML from repository-local automation into an organization-wide delivery framework with reusable, reviewable standards.