YAML Lint / Guides

YAML anchors and aliases

Anchors (&) name a chunk of YAML so you can reuse it elsewhere with an alias (*). The merge key (<<:) extends the trick to mix anchored maps with extra keys. Together, they're the cleanest way to remove copy-paste from a YAML config.

Validate your config →

The basic shape

An anchor declares the value; an alias copies it.

defaults: &defaults
  retries: 3
  timeout: 30
  log_level: info

dev:
  <<: *defaults
  log_level: debug

prod:
  <<: *defaults
  retries: 5

After parsing, this resolves to:

defaults:
  retries: 3
  timeout: 30
  log_level: info

dev:
  retries: 3
  timeout: 30
  log_level: debug

prod:
  retries: 5
  timeout: 30
  log_level: info

The &defaults anchor names that map; the *defaults alias inserts a reference to it; the <<: merge key tells the parser "merge the anchored map's keys into the parent." Local keys (like log_level: debug) override anchored ones.

Anchors work on any value

Anchored list

standard_ports: &ports
  - 80
  - 443

http_app:
  ports: *ports

api_app:
  ports: *ports

Anchored scalar

app_name: &name billing-service
service_id: *name
display_name: *name

Both service_id and display_name become the string "billing-service". Useful when the same value appears in many places and you want one place to change it.

Multi-merge: combining several anchored maps

The merge key accepts a list of aliases. Earlier items take precedence on conflicts:

postgres: &postgres
  driver: postgres
  port: 5432

logging: &logging
  log_level: info
  log_destination: stdout

prod_db:
  <<: [*postgres, *logging]
  host: db.prod.example
  log_level: warn

After resolution, prod_db has every key from both postgres and logging, plus its own keys, with log_level: warn winning over log_level: info.

Gotchas

Merge key isn't standard YAML 1.2

The merge key (<<:) was a YAML 1.1 feature kept by convention. The 1.2 spec doesn't formalize it; almost every popular parser supports it anyway, but a strict 1.2-only parser may not. Test in your toolchain.

Anchors don't span files

Each YAML document is a closed scope. You can't define an anchor in defaults.yaml and use the alias in prod.yaml. For cross-file reuse, you need a templating layer or a tool that merges files (Helm, Kustomize, etc.) before the YAML parser sees them.

Override only works one level deep

The merge key replaces top-level keys, not nested ones. If you want to override a single field inside a nested map, you have to either re-specify the whole map or restructure to put the overridable field at the top level.

Aliases resolve to copies

After parsing, two uses of the same alias produce independent copies of the data. Mutating one in your application code doesn't affect the other. Don't expect JavaScript-style reference semantics.

Forward references aren't allowed

The anchor must appear before any alias that references it. YAML is a streaming format and parsers resolve aliases as they go.

When to use anchors vs a templating engine

NeedTool
Reuse within one fileAnchors + merge keys
Reuse across filesHelm / Kustomize / Jinja / etc.
Per-environment valuesTemplating engine
Computed values from other inputsTemplating engine
Schema validationJSON Schema (validates either)

Reference

FAQ

Are anchors and aliases the same as references in JavaScript?

No — they're a serialization trick, not runtime references. After parsing, you have a copy of the data, not a shared object. Mutating the resolved value doesn't affect the anchor's other uses (because there's no anchor anymore by the time your code sees it).

Does the merge key <<: work in every YAML parser?

It's not part of the YAML 1.2 core spec — it's a 1.1 feature that was kept by convention. Most popular parsers (PyYAML, snakeyaml, js-yaml, the npm 'yaml' package, ruby/yaml) support it. Niche parsers may not. Check your parser's docs if portability matters.

Can I anchor a string and reuse it?

Yes. Anchors work on any value — scalars, lists, maps. `name: &n my-app` lets you use `*n` later for the same string. In practice, anchors on scalars are rare; the win is reusing whole map blocks via merge keys.

What's a 'billion laughs' attack?

An aliased anchor that exponentially expands when resolved. `a: &a [1, 1, 1, 1, 1, 1, 1, 1, 1]; b: &b [*a, *a, *a, *a, *a, *a, *a, *a, *a]; c: &c [*b, *b, *b, *b, *b, *b, *b, *b, *b]; ...` — each level multiplies the size 9× and parsers without alias-count limits run out of memory. Most modern parsers cap alias expansion (the 'yaml' npm package limits to 100 by default).

Should I use anchors instead of a templating engine?

For repetition inside a single file, yes — anchors are simpler than introducing Jinja or Handlebars. For repetition across files, no — anchors don't span files. For dynamic values that change per environment, no — anchors are static. Use the right tool.

Open the YAML linter →