Guide · Jul 13, 2026

YAML Anchors and Aliases: Reusing a Value Without Repeating It

A CI config with ten similar jobs, each needing the same base environment settings. A Docker Compose file where three services share identical resource limits. The naive approach is copy-pasting the same block into every job or service — which works, until the shared settings need to change and now there are ten places to update instead of one. YAML has a built-in answer to exactly this, and it's one of the few things it can express that JSON genuinely can't.

The basic mechanic

An anchor, written as &name right after a key, marks a value as reusable and gives it a label. An alias, written as *name, references that labeled value anywhere else in the document — at parse time, the alias is replaced with an exact copy of whatever the anchor pointed to.

base: &defaults
  timeout: 30
  retries: 3

service_a:
  <<: *defaults
  name: a

service_b:
  <<: *defaults
  name: b
  timeout: 60

The <<: syntax specifically merges the anchored mapping's keys into the current one, rather than assigning it as a single nested value — which is why service_b ends up with both retries: 3 (inherited) and its own timeout: 60 (overriding the inherited default), a pattern that's genuinely useful for "shared defaults with per-item overrides" configs.

What actually gets shared vs copied

It's worth being precise about what an alias does at parse time: it produces an independent copy of the anchored value in the resulting data structure, not a live link back to the original. Once parsed, editing one instance in code afterward doesn't affect the other — the anchor/alias relationship only exists in the YAML source text, as a way to avoid repeating yourself while writing it, not as a runtime reference that persists after parsing.

Why this doesn't survive a trip to JSON

JSON has no concept of an anchor or alias — nothing in its spec lets one part of a document reference another. Converting YAML with anchors to JSON resolves every alias into its fully expanded form, which is why a compact YAML file using anchors heavily can turn into a noticeably larger JSON file: the JSON has to spell out every repeated block in full, since it has no shorthand for "same as that other one." This is expected, not a bug in the conversion — it's just JSON losing a piece of structure it was never designed to represent, similar to how it also can't carry over YAML comments.

Where this shows up most in practice

Kubernetes manifests, Docker Compose files, and CI/CD pipeline configs (GitHub Actions, GitLab CI) are the places this pattern gets used most, since those formats commonly have several similar-but-not-identical definitions in one file — several jobs sharing a runner image and environment variables, several services sharing resource limits, several deployments sharing a base container spec. Anywhere a config file has that "same thing, several times, with small variations" shape is a candidate for anchors.

See the expanded form

FreeToolDev's JSON ↔ YAML converter is a quick way to see exactly what an anchor-heavy YAML file expands into — paste it in, convert to JSON, and see every alias resolved into its full, repeated form, which can be a useful sanity check when debugging whether a merge is producing the values you expect.