TL;DR
|
A YAML file is a plain text file that stores settings and other structured information in a format both people and programs can read. It uses indentation and simple punctuation, like colons and dashes, to show how pieces of information relate to each other.
You will usually meet YAML when a tool asks you to configure it: a deployment pipeline, a container setup, or a hosting platform. This guide explains how YAML is put together, walks through real examples, and covers the handful of mistakes behind most broken YAML files.
Key takeaway: YAML is one of the most common formats for configuration files in development tools, because people can read and edit it without special software.
The name is a recursive joke: YAML stands for "YAML Ain't Markup Language". The point is that YAML describes data, such as settings, lists, and options, rather than formatting a document the way HTML does.
You will find YAML files in many of the tools developers use every day:
| Tool | What the YAML file does | Typical file name |
|---|---|---|
| GitHub Actions | Defines automated workflows, such as running tests on every change | .github/workflows/test.yml |
| Docker Compose | Describes several containers that run together on your computer | compose.yaml |
| Kubernetes | Describes the containers, networks, and storage an app needs | Any name ending in .yaml or .yml |
| Upsun Cloud | Describes a project's apps, services, and routes in one place | .upsun/config.yaml |
Configuration files are read and changed by people far more often than they are written from scratch, which is where a readable format pays off. YAML files often sit alongside other configuration files in a project, such as a .env file that holds secrets. Our guide What is .env? covers that one.
Key takeaway: almost every YAML file is built from key and value pairs, indentation for nesting, and dashes for lists.
Here is a short YAML file for a made-up web app. Every part of it is explained below.
# Settings for a small web app
app_name: recipe-finder
port: 8080
debug: false
database:
host: localhost
name: recipes
features:
- search
- favorites
- shopping-list
welcome_message: |
Welcome to Recipe Finder.
Search by ingredient to get started.| Piece | Example from the file | What it means |
|---|---|---|
| Comment | # Settings for a small web app | A note for people. Anything after # is ignored. |
| Key and value | app_name: recipe-finder | A setting name, a colon, a space, then its value. |
| Number | port: 8080 | YAML reads values that look like numbers as numbers. |
| True or false | debug: false | Values like true and false are read as on and off switches. |
| Nested group | database: with two indented lines below it | Indented lines belong to the key above them, so host and name are both part of database. |
| List | - search | Each line starting with a dash and a space is one item in a list. |
| Multi-line text | welcome_message: | | The pipe keeps the line breaks in the text that follows. |
Text usually needs no quotes, but you can add single or double quotes around any value. Quotes are how you tell YAML to treat something as text when it looks like a number or a switch (see the mistakes section below).
Indentation carries the structure. A line indented under a key belongs to that key, and lines at the same indentation are siblings. The exact number of spaces is up to you, as long as each level is consistent. Two spaces per level is a common choice.
Key takeaway: YAML and JSON can hold the same information. YAML is easier for people to read and edit, and JSON is stricter and more common for data sent between programs.
JSON is another text format for structured data, used heavily by websites and APIs. Here is the same app configuration from above, written as JSON:
{
"app_name": "recipe-finder",
"port": 8080,
"debug": false,
"database": {
"host": "localhost",
"name": "recipes"
},
"features": ["search", "favorites", "shopping-list"],
"welcome_message": "Welcome to Recipe Finder.\nSearch by ingredient to get started.\n"
}| YAML | JSON | |
|---|---|---|
| Structure shown by | Indentation | Curly and square brackets |
| Comments | Allowed, with # | Not allowed |
| Quotes around text | Usually optional | Always required |
| Multi-line text | Built in, with | | Needs \n for each line break |
| Main weakness | Easy to break with a stray space | Hard to read and edit by hand |
| Typical use | Configuration files people edit | Data passed between programs |
The two are closely related. YAML 1.2, the current version of the YAML specification, was designed so that JSON is valid YAML. That is why some tools accept either format for the same file.
Key takeaway: most YAML problems are indentation or spacing mistakes, and the worst ones raise no error at all. The file loads, but it means something different from what you wrote.
YAML errors come in two kinds. Some stop the file from loading and show an error message, which is annoying but easy to spot. Others load without complaint and quietly change your settings, so the app runs with values you never meant to set. Where it helps, each mistake below shows the broken version first, then the fix.
YAML does not allow tab characters for indentation. A single tab, often added by an editor without you noticing, makes the whole file fail to load.
Fix: set your editor to insert spaces when you press Tab. Most code editors have this setting, and many apply it to YAML files automatically.
If a line ends up one level too far left, it stops belonging to the group above it. YAML reads it as a separate setting, with no error.
# Broken: name is no longer part of database
database:
host: localhost
name: recipes
# Fixed
database:
host: localhost
name: recipesA line indented by one space too many usually does produce an error, often worded as "mapping values are not allowed here". If you see that message, check the indentation of the line it points to and the line above it.
YAML needs a space after the colon in key: value and after the dash in a list item. Without it, YAML sees ordinary text.
# Broken: read as one line of text, not a list
features:
-search
-favorites
# Fixed
features:
- search
- favoritesA colon followed by a space inside a value confuses YAML, because it looks like the start of a new setting.
# Broken: fails to load
message: Note: restart the app after changes
# Fixed
message: "Note: restart the app after changes"YAML guesses what kind of value you mean, and sometimes it guesses wrong. These are the classic surprises:
| You wrote | You meant | What YAML may read |
|---|---|---|
| version: 1.10 | Version one point ten | The number 1.1 |
| zip_code: 01234 | A code with a leading zero | A number, which drops the leading zero or changes the value entirely |
| country: NO | Norway | The value false, in tools that follow the older YAML 1.1 rules |
| answer: yes | The word yes | The value true, in the same older tools |
Fix: put quotes around any value that must stay as text, such as version: "1.10" or country: "NO". Leave quotes off values a tool expects as real numbers or true and false switches, such as a port number.
If the same key appears twice at the same level, many tools keep the last value and ignore the first without telling you. Stricter tools stop with an error instead.
port: 8080
# ...many lines later
port: 9090The app runs on port 9090, and the first line is silently ignored. In a long file, search for the key before adding it.
Key takeaway: let a tool check your YAML. An editor extension catches mistakes as you type, and a validator confirms the whole file before you rely on it.
There are three common ways to check a YAML file, from lightest to most thorough:
Online YAML validators work too, but be careful with what you paste into them. Configuration files sometimes contain passwords or internal addresses, and those should not go into a website you do not control.
If an AI assistant wrote the file, check it the same way. AI-generated YAML often has valid syntax, so it loads without errors. The mistakes tend to be in the content instead: a setting name the tool doesn't recognize, an option from an older version of the tool, or a value at the wrong level. A tool's own checker, option 3 above, is the one most likely to catch them.
Key takeaway: Upsun Cloud describes an entire project in one YAML file, .upsun/config.yaml, and its command line tool can check that file before you deploy.
On Upsun Cloud, the apps you run, the services they use (such as a database), and the web addresses that reach them all live in one YAML file. It sits in a folder called .upsun at the top of your project. Running upsun project:init creates a starting version based on the code it finds.
Here is a small example: a Node.js app connected to a PostgreSQL database.
applications:
myapp:
type: "nodejs:26"
relationships:
database:
web:
commands:
start: "node index.js"
services:
database:
type: "postgresql:17"
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"Here is what each part does:
The common mistakes above apply here too. A misplaced indent can move relationships out from under myapp. The quotes in this example are optional, but quoting values that contain colons or curly braces is a safe habit.
To check the file before you push it, run upsun app:config-validate in your project folder. It validates your project's configuration files, so mistakes surface on your machine before a deployment does. If a coding agent edits this file for you, tell it to run the same command after every change. Our guide What is an AGENTS.md file? shows how to write that instruction down once so every agent follows it. You can also connect your editor to Upsun Cloud's published schema, so it suggests valid settings and flags mistakes as you type. The Upsun Developer Center explains how to set that up.
For everything the file can contain, see YAML on Upsun Cloud in the Upsun docs.
On Upsun Cloud, this one file describes your whole project, and every environment is built from it. You can deploy on Upsun Cloud free for 15 days, with no card needed, or see how Git-driven automation turns configuration changes into deployments.
YAML stands for "YAML Ain't Markup Language". The name makes the point that YAML is for describing data, such as settings and lists, rather than formatting documents.
Nothing. Both extensions mean the same format. Some tools expect one or the other, so use whichever the tool's documentation shows.
No. YAML only allows spaces for indentation. Set your editor to insert spaces when you press Tab.
Any number works as long as each level is consistent. Two spaces per level is a common choice.
This error usually means a line is indented differently from its neighbors, or a value contains a colon followed by a space. Check the indentation of the line the error points to, and put quotes around any value that contains a colon.
Neither is better in general. YAML is easier for people to read and edit, which suits configuration files. JSON is stricter and simpler for programs to produce, which suits data sent between systems.
Any text editor can open it, because a YAML file is plain text. A code editor with a YAML extension makes it easier to read and to spot mistakes.