Every microservices team eventually reinvents the same pipeline. They copy and paste the YAML from the last service they built, change the image name, and call it done. For a while, it works fine.
Then a security vulnerability surfaces and you need to add a container scan step to every pipeline. Or you want to enforce a consistent artifact naming scheme. Or someone needs to change how environment variables are injected. Suddenly you’re touching 30 pipelines individually, hoping you get them all — and hoping they’re consistent enough to actually find.
This is the problem portable pipelines solve.
The core idea
A portable pipeline extracts the shared logic — build, test, scan, push, deploy — into a template that individual services consume with minimal configuration. The service pipeline becomes thin:
# azure-pipelines.yml (in a microservice repo)
resources:
repositories:
- repository: pipeline-templates
type: git
name: platform/pipeline-templates
extends:
template: service-pipeline.yml@pipeline-templates
parameters:
serviceName: order-service
dockerRegistry: myregistry.azurecr.io
deployEnvironments:
- staging
- production
The actual logic — what “build” means, what quality gates run, how artifacts are tagged, how deployments are sequenced — lives in the shared template repository, maintained by the platform team.
Why this matters
Fixes propagate automatically. When you add the container scan step to service-pipeline.yml, every service that extends it gets the change on their next pipeline run. No manual updates, no stragglers.
Consistency becomes the default. Every service builds the same way, tags images the same way, and runs the same quality gates. Audits and compliance checks become tractable.
Teams move faster. A new microservice gets a production-ready pipeline in under a minute. The team doesn’t need to understand every detail of the deployment process — they just consume the template and focus on their service.
The platform team has leverage. Instead of acting as a support desk for pipeline questions, the platform team ships improvements to the template and everyone benefits.
What it looks like at scale
At GrandVision we ran a multi-tenant microservices platform on Azure — multiple product teams, each owning several services, all deploying to AKS. The pipeline landscape before portable pipelines was exactly what you’d expect: each team had solved the same problems in slightly different ways, quality gate coverage was uneven, and any cross-cutting change required coordination across every team.
After introducing pipeline templates via Azure DevOps, onboarding a new service went from “copy the YAML from service X, remember to change these 7 things” to extending the template with a name and a registry URL.
The approach also surfaced an important cultural shift: the platform team stopped being the people who helped other teams write pipelines, and started being the team that owned the pipeline product. The distinction matters.
Pitfalls
Versioning. If you update the template and it breaks something, every consuming service breaks simultaneously. Pin to tagged releases of your template repository, not to a branch. Introduce changes through feature flags or opt-in parameters first.
Overfitting. Templates are powerful until they try to do too much. A single template that handles 12 different deployment strategies with 40 parameters is not portable — it’s a new source of complexity. Keep templates narrow and composable.
Ownership. Shared templates need a clear owner. The platform team should own them like a product: versioned, documented, with a changelog. If nobody owns the templates, they rot.
Where this applies beyond Azure DevOps
The pattern translates to any modern CI/CD system:
- GitHub Actions → Reusable Workflows
with
workflow_call - GitLab CI →
includewith remote template files - Jenkins → Shared Libraries
- Tekton → Pipeline bundles and
ClusterTaskresources
The tooling differs. The principle is the same: extract the shared logic, version it, let teams consume it.
The talk that accompanied this post was recorded at a GrandVision internal platform session. A later version was presented publicly — watch it here .