YAML Merge Keys

Repeating the same settings in many places wastes time and invites mistakes. A merge key copies the contents of one mapping into another. Combined with an anchor, it lets you write shared settings once and reuse them everywhere. Changes to the shared block flow through to every copy automatically.

A Quick Reminder About Anchors

An anchor labels a block with an ampersand. Aliases refer back to that label with an asterisk. A merge key takes the aliased mapping and pours its keys into the current one.

The Merge Syntax

The merge key is written as two angle brackets followed by a colon: <<. The value is an alias.

defaults: &defaults
  color: blue
  size: medium
  stock: 10

shirt:
  <<: *defaults
  name: Polo

hat:
  <<: *defaults
  name: Cap

Both shirt and hat receive color, size, and stock from the defaults block. Each also keeps its own name.

What the Parser Builds

 defaults  ----+
 color: blue   |
 size: medium  +--> copied into --> shirt: color, size, stock, name: Polo
 stock: 10     |
               +--> copied into --> hat:   color, size, stock, name: Cap

The parser expands every merge before your program sees the data. The final result contains full, separate mappings with no merge keys left over.

Overriding Merged Values

Keys written directly in the mapping win over merged keys. Use that rule to adjust a single setting.

jacket:
  <<: *defaults
  name: Parka
  color: black
  stock: 3

The jacket keeps the size from the defaults and replaces the color and stock. This approach describes a family of similar items with minimal typing.

Merging Several Sources

A list of aliases merges more than one mapping:

base: &base
  restart: always
  network: main

logging: &logging
  log_driver: json-file
  log_level: info

web:
  <<: [*base, *logging]
  image: nginx

When two sources contain the same key, the one listed earlier takes priority. Put the most important source at the front of the list.

PrioritySource
HighestKeys written directly in the mapping
NextFirst alias in the merge list
LowestLast alias in the merge list

Where Merge Keys Work

The merge key comes from YAML 1.1 and sits outside the core YAML 1.2 specification. Most popular libraries support it, including PyYAML and the parsers inside Docker Compose, GitLab CI, and many other tools. A few strict parsers ignore it and treat << as an ordinary key.

  • Test the feature in the exact tool you use.
  • Read the tool documentation for merge support.
  • Check that the final merged data looks correct by printing it.

Merging Shallow Only

A merge copies top-level keys only. Nested mappings do not combine automatically. A nested key in the local mapping replaces the whole nested block from the source.

base: &base
  db:
    host: localhost
    port: 5432

prod:
  <<: *base
  db:
    host: prod.example.com

The production mapping ends up with a db block holding only the host. The port from the base disappears. Remember this limit when you design layered settings.

Good Habits

  • Name anchors by purpose, such as defaults or common.
  • Place anchor definitions near the top of the file.
  • Keep merged blocks small and focused.
  • Add a comment above each anchor explaining what it shares.

A Real-Life Comparison

A restaurant chain shares one base menu across every branch. A single branch adds a local dish and changes one price. The base menu plays the role of the anchor, and each branch file merges it and lists only the differences. Updating the base menu updates every branch at once.

Merge keys reward careful planning. A clear base block, short overrides, and honest comments keep large files readable.