Anchors, aliases and merge keys

YAML · Practical · 10 min

They remove copy-paste from big config files such as CI pipelines and Docker Compose services.

An anchor &name labels a node; an alias *name later in the same document refers to that same node. The parser expands it, so the resulting data contains the value twice (in many libraries literally the same object).

defaults: &defaults
  retries: 3
  timeout: 30
job_a: *defaults

To reuse a mapping but override or add some keys, many parsers support the merge key <<:

job_b:
  <<: *defaults
  timeout: 60

job_b gets retries: 3 and its own timeout: 60; explicit keys win over merged ones. <<: [*a, *b] merges several, earlier ones taking precedence.

Caveats:

  • The merge key was defined for YAML 1.1 and is not part of YAML 1.2. PyYAML, ruamel.yaml, Go's yaml.v3 and js-yaml support it, but some parsers and tools don't.
  • Anchors work only within one document and must be defined before use.
  • Aliases are expanded on load, so dumping the data back usually doesn't restore them.
  • Tools like Docker Compose ignore top-level keys starting with x-, a convenient place to keep anchor definitions that aren't themselves config.

Example

x-defaults: &defaults          # x- keys are ignored by Docker Compose
  restart: unless-stopped
  logging:
    driver: json-file
  environment: &env
    TZ: UTC

services:
  api:
    <<: *defaults
    image: example/api:2.1
  worker:
    <<: *defaults
    image: example/worker:2.1
    restart: on-failure        # overrides the merged value
    environment: *env          # plain alias of a nested node

# worker parses to:
# {restart: on-failure, logging: {driver: json-file},
#  environment: {TZ: UTC}, image: example/worker:2.1}

Remember

  • &name defines an anchor, *name reuses that node
  • <<: *anchor merges a mapping; explicit keys override merged ones
  • Merge keys are a YAML 1.1 feature, widely but not universally supported

Watch out for

  • Expecting an anchor defined in one document (or one file) to be available in another.

Check yourself

  1. With base: &b {a: 1, b: 2} and c: {<<: *b, b: 3}, what is c?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: yaml.org/type/merge.html