Skip to content

YAML Variables Don’t Exist. Here’s How to *Actually* Reuse Code in 2026

26/01/2026

Technical review: 27 October 2026. This is a supplementary guide from the previous course, not a numbered chapter of the new course. Follow the current Home Assistant YAML course for the learning sequence.

YAML is the data serialization language that forms the backbone of countless DevOps and IoT projects, from configuring Home Assistant to defining workflows in GitHub Actions. Its popularity comes from a clean, human-readable syntax. However, one of the most common questions I hear is how to handle YAML variables to avoid repeating code.

Let’s get one thing straight right from the start: YAML, in its core spec, doesn’t have “variables” like you’d find in a programming language like Python or JavaScript. You can’t declare a variable and then modify it later. Instead, YAML offers a much more powerful mechanism that fits its declarative nature for reusing YAML values: Anchors and Aliases.

In this definitive 2026 guide, we’re going to bust the myth of variables in YAML. I’ll show you the standard, correct method for reusing data, and we’ll also explore platform-specific techniques that often get confused with native variables.

The Right Way: Mastering YAML Anchors & Aliases

YAML’s native solution to the DRY (Don’t Repeat Yourself) principle is built on two components: anchors and aliases. This is the technique you should always prioritize, as it’s part of the YAML standard and will work with any compliant parser.

  • Anchor: Used to mark a value with a name. The syntax is &anchor_name.
  • Alias: Used to reference (and thus, reuse) a value previously marked with an anchor. The syntax is *anchor_name.

Think of it like putting a label on a piece of data so you can “paste” that same data anywhere else in your document. Let’s look at a practical example to really nail it down.

Real-World Example: DRYing Up a Docker Compose File

Imagine you’re setting up multiple services in a docker-compose.yml file, and they all need the same environment variables to connect to a database. Instead of repeating them, we use anchors.

# Define a block of environment variables and mark it with the &db_env anchor
x-environment: &db_env
  DB_HOST: postgres_db
  DB_USER: admin
  DB_PASS: supersecret_password_123

services:
  backend_app:
    image: my-app:latest
    environment:
      # Use the *db_env alias to insert the entire block
      <<: *db_env
      PORT: 8000

  worker:
    image: my-worker:latest
    environment:
      # Reuse the same block here
      <<: *db_env
      QUEUE_NAME: "high_priority"

In this example, we define the &db_env anchor just once. Then, using the *db_env alias, we inject that data block into two different services. If the database password changes, you only have to update it in one place. This is a cornerstone of clean, maintainable YAML.

Going Modular: Splitting Configs with !include

When your configuration files get massive, even anchors aren't enough to keep things tidy. This is where application-specific directives like !include come in, which is extremely popular in the Home Assistant ecosystem.

Heads Up: !include is not part of the YAML standard, but it's such a common extension that you need to know about it. It allows you to load the content of another YAML file into your current one.

Example of !include in Home Assistant

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

Keep your existing entries rather than duplicating them. The included automation and scene files contain lists; the scripts file contains a map. An included file does not repeat its parent key. Integration configuration that has moved to the UI should not be restored through obsolete YAML platforms.

Beyond the Standard: Templating Engines & Custom Tags

This is where the original confusion about YAML variables usually comes from. Many tools use YAML as a base but add their own templating engine to process the file *before* interpreting it as pure YAML. This allows for more complex logic but is specific to each platform.

Home Assistant: variables and Jinja, not a !var tag

Home Assistant does not provide a built-in !var tag. The previous example was incorrect and has been removed. Script and automation variables are defined in their supported variables: fields and read with Jinja in fields that support templates. Do not assume every trigger field accepts a template or can read a variable defined later in the action sequence.

Example for an individual script in the script editor’s YAML view:

alias: "Variable example"
sequence:
  - variables:
      notification_title: "Home Assistant notice"
  - action: persistent_notification.create
    data:
      title: "{{ notification_title }}"
      message: "This value comes from a script variable."

This example creates a notification without requiring a phone service. YAML defines the structure; Home Assistant evaluates the Jinja expression at runtime. For the distinction, see YAML and Jinja in Home Assistant.

Case Study 2: Ansible (Jinja2) & GitHub Actions

To broaden our perspective, let's see how other popular tools handle value reuse:

  • Ansible: Uses the Jinja2 templating engine. Variables are defined in various places (inventory, playbooks, vars files) and are referenced with double curly braces: {{ my_variable }}.
  • GitHub Actions: Has its own expression context to access variables, secrets, and workflow data. The syntax is ${{ secrets.MY_SECRET }} or ${{ inputs.parameter_name }}.

Loading and evaluation order depend on the tool. They do not all substitute values before parsing YAML: Home Assistant evaluates many templates at runtime.

YAML Variables: Which Method Should You Use?

To wrap it all up, I've created this table to clarify when to use each method.

MethodSyntaxPrimary Use CaseCompatibility
Anchors (&) & Aliases (*)&anchor / *anchorReusing any value or block (scalars, lists, maps) within the same YAML file.YAML Standard. Works in any compliant parser (Kubernetes, Docker, etc.).
!include Directive!include filename.yamlSplitting a large configuration into multiple smaller, manageable files.Non-standard. Application-dependent (very common in Home Assistant).
Platform-Specific Templating{{ variable }}, ${{ context }}Accessing dynamic variables, secrets, or performing complex substitutions before YAML parsing.Non-standard. Specific to each tool (Home Assistant, Ansible, GitHub Actions).

The Payoff: Why Reusing YAML Values is a Game-Changer

Regardless of the method you choose (though I strongly recommend starting with Anchors and Aliases), the benefits are clear and universal:

  1. Code Reusability: The most obvious win. You avoid copy-pasting, which dramatically reduces the chance of typos and errors.
  2. Simplified Maintenance: When a shared value needs to change (like an IP address, token, or threshold), you only update it in one place. This is a lifesaver in large projects.
  3. Improved Readability: By defining common configuration blocks with a descriptive name (using an anchor, for example), the code's intent becomes clearer and self-documenting.

Mastering these techniques will not only make you more efficient but will also elevate the quality and robustness of your configurations, turning them into projects that are maintainable for the long haul. The next time you're facing a messy YAML file, remember you have powerful tools to keep it clean and organized.

Security note: anchors do not protect credentials. The Compose password above is a fictitious example, not a recommendation to publish secrets. The merge key is processor-dependent and does not recursively merge nested maps.