YAML Anchors and Merge: DRY Configs Without Hidden Coupling
Anchors and the merge key << can make YAML configs DRY, but they introduce hidden coupling and parser variance. Here is how to use them safely for environment overrides with a concrete example and verifiable limits.
30 Oct 2025, 17:19 UTC

Copy-paste is the first sign a YAML config is about to rot. You start with one Kubernetes Deployment for a service, then you need dev, staging and prod. The temptation is to duplicate the whole block and change replicas, resources and image tag. After three environments the file is hundreds of lines long and a single security patch requires three edits.
The useful takeaway is that YAML already has a built-in DRY mechanism: anchors with &name and aliases with *name, often combined with the merge key <<. Used deliberately they cut duplication. Used carelessly they create hidden coupling that makes reviews hard and breaks on strict parsers.
Anchors and aliases give you reuse by reference
An anchor marks a node for later reuse. An alias points back to it. This is core YAML 1.1 and 1.2 and is supported by most mainstream parsers.
Anchors improve maintainability for small, localized duplication, but edits to the anchor affect all aliases implicitly. That is the coupling. In a diff you see a change in one place with effects in many places, which can surprise reviewers.
Merge key << gives you inheritance for mappings
The merge key << is a widely implemented YAML 1.1 extension. It lets a mapping inherit entries from one or more other mappings. The typical pattern is a base defaults map, then an environment map that merges the base and overrides specific keys.
Important limitation: << is not part of the YAML 1.2 core specification. It is a YAML 1.1 extension. Support and behavior can vary across parsers and strict 1.2 implementations. Order of precedence and handling of nested merges is version-sensitive.
Worked example: base service with environment overrides
The engineering decision here is to define the common shape once, then alias it and merge only the differences.
defaults: &service_defaults
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: payments
spec:
replicas: 2
template:
spec:
containers:
- name: payments
image: registry.example/payments:1.0.0
resources:
requests:
cpu: "100m"
memory: "128Mi"
dev:
<<: *service_defaults
spec:
replicas: 1
template:
spec:
containers:
- name: payments
image: registry.example/payments:dev
prod:
<<: *service_defaults
spec:
replicas: 5
template:
spec:
containers:
- name: payments
image: registry.example/payments:1.0.0
resources:
requests:
cpu: "500m"
memory: "512Mi"
The anchor &service_defaults defines the node once. dev and prod alias it via <<: *service_defaults and then override replicas, image and resources. The merged result for each environment contains the base keys plus the overrides.
To verify behavior in your stack, create a small file with an anchored mapping and an alias, load it with the parser you actually use, and inspect that the aliased node has the same content as the anchor. Then test a mapping using << with two base maps and an override map, load it and check the resulting merged key set matches expected precedence. Comparing the same file with two different parser implementations can surface differences in merge key support and anchor preservation.
Trade-offs and practical limits
Anchors and merge reduce copy-paste but create implicit coupling. A change to the anchor propagates to every alias without an explicit reference in the diff. Not all tools preserve anchors on load and dump round-trips, so programmatic edits can silently lose the DRY structure.
Merge key << also makes reviews harder. The final shape of a mapping is not visible in one place; you have to mentally resolve the merge chain. For deep nesting, precedence rules differ between implementations.
Actionable closing
Use anchors for small, stable blocks that truly repeat, such as labels, resource requests, or common container specs. Keep the merge chain shallow, one base plus one override per environment. Document which parser version you require and pin it in CI.
Avoid using << in files that must be portable to strict YAML 1.2-only tools. If you need guaranteed portability, prefer explicit composition in your application code instead of YAML-level inheritance. When you do use anchors, add a comment next to each alias stating what it inherits from, so reviewers can see the coupling without chasing references.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.