Reuse YAML configuration with anchors and aliases
YAML anchors and aliases let you define configuration once and reference it many times in one file. Learn the shared-reference trap and when to repeat yourself.
05 Oct 2026, 23:30 UTC

The problem: repeating the same connection block five times
You are maintaining a deployment file with separate entries for an API, a worker, a scheduler, and two background jobs. Each entry repeats the same database host, port, and credentials. When the password rotates, you edit four places and miss the fifth. Tests pass locally, but staging fails to connect.
YAML offers a built-in way to avoid this repetition inside a single file: anchors and aliases. The ampersand (&) marks a node for reuse, and the asterisk (*) references that marked node later in the document. Both are part of the YAML 1.1 and 1.2 specifications and are supported by mainstream libraries such as PyYAML, SnakeYAML, Go yaml.v3, and Ruby Psych.
The useful takeaway is narrow: anchors and aliases are excellent for static defaults in one file, but they create references to the same in-memory object. If your application mutates loaded configuration, every alias sees the change.
Worked example: shared database defaults
Instead of repeating connection details under every service, define them once with an anchor and alias them where needed.
# services.yaml
db_defaults: &db_defaults
host: db.example.com
port: 5432
username: app
services:
api:
database: api_db
connection: *db_defaults
worker:
database: worker_db
connection: *db_defaults
scheduler:
database: scheduler_db
connection: *db_defaults
Here &db_defaults labels the mapping under db_defaults. Each *db_defaults inserts that same mapping as the value of connection. The file is valid core YAML; it does not rely on merge keys (<<), which are a common extension but not part of the core specification.
Verify parsing and identity
Run this from the directory containing services.yaml. No special permissions are required.
python3 - <<'PY'
import yaml
with open("services.yaml", "r", encoding="utf-8") as handle:
data = yaml.safe_load(handle)
api_conn = data["services"]["api"]["connection"]
worker_conn = data["services"]["worker"]["connection"]
print("equal:", api_conn == worker_conn)
print("same object:", api_conn is worker_conn)
PY
Expected checks: equal prints True. same object commonly prints True with PyYAML because aliases resolve to the same parsed object, though identity can depend on the library and loader settings. A risk is assuming identity is guaranteed everywhere; treat equality as the contract and verify identity only if your code depends on it.
The aliasing trap: mutation affects every reference
Because an alias points to the same in-memory node, changing one aliased structure changes them all. Continuing the Python example:
api_conn["host"] = "db.internal.example.com"
print(worker_conn["host"]) # db.internal.example.com
If your code loads this file once and then adjusts connection per service at runtime, the edit leaks to every service. The practical fix is to deep-copy aliased structures before mutating them, or to avoid aliases for any configuration your application will modify after loading.
Merge keys, portability, and limits
You will often see merge keys written as <<: *db_defaults to spread anchor fields into the current mapping. Merge keys are widely supported by PyYAML, SnakeYAML, and Psych, but they are not part of the core YAML specification. Strict validators and some language parsers reject them. If portability across tools is critical, repeat fields explicitly or use a templating layer instead of relying on <<.
Other hard limits:
- Anchors and aliases work within one document only. You cannot anchor a node in
file-a.yamland alias it infile-b.yaml. - Circular anchors are forbidden. A node cannot reference itself directly or indirectly; the parser will reject the document.
- Aliases share object identity, which is useful for memory efficiency but dangerous for mutable runtime state.
When to use anchors, and when to repeat yourself
Use anchors for static, read-only defaults inside a single YAML file: database connection blocks, default resource limits, or shared CI environment variables. Do not use them when your application mutates loaded config, when you need to share values across files, or when strict schema validation must pass in multiple parsers.
A practical way to check the result is to load the same file with two different libraries—for example, PyYAML and Go yaml.v3—and confirm that both produce equal values for aliased fields. If they disagree, or if a strict parser fails, fall back to explicit repetition.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.