YAML Cheat Sheet
This YAML cheat sheet contains every syntax, every element - searchable, filterable by version, copy-ready, with parsed-output previews.
What Is YAML?
YAML is a human-readable data serialization format used to represent structured data in plain text. The acronym stands for "YAML Ain't Markup Language," a recursive name that signals its creators didn't want it treated as just another document markup language.
Clark Evans, Ingy döt Net, and Oren Ben-Kiki created YAML in 2001, drawing influence from Python's indentation-based syntax, Perl's data-handling modules, and the broader XML community's push for simpler alternatives.
Key distinction from XML and JSON: YAML uses indentation and plain text to define structure. No angle brackets. No curly braces required at the top level. What you write looks close to how you'd describe data verbally.
YAML files use either .yaml or .yml as file extensions. Both are interchangeable. Most tooling accepts either.
Over 60% of developers now use YAML in DevOps workflows, according to a 2025 survey cited by MoldStud, reflecting how central the format has become to modern infrastructure tooling.
Where YAML Is Used
Primary use cases:
-
Configuration files for Kubernetes, Docker Compose, and Ansible
-
CI/CD workflow definitions in GitHub Actions and GitLab CI
-
Infrastructure as code manifests
-
Data exchange between systems and services
-
OpenAPI specification files
Kubernetes alone had 5.6 million developers using it globally as of 2024 (CNCF), and every Kubernetes manifest is written in YAML. That gives you a rough sense of the format's reach.
YAML vs. Other Formats at a Glance
|
Feature |
YAML |
JSON |
TOML |
|---|---|---|---|
|
Comments |
Yes ( |
No |
Yes |
|
Readability |
High |
Medium |
High |
|
Multiline strings |
Yes (native) |
Limited |
Yes |
|
Type coercion |
Implicit (tricky) |
Explicit |
Explicit |
|
Best for |
Deep config, IaC |
APIs, data transfer |
Flat config files |
|
Superset of JSON |
Yes |
No |
No |
What Are the Core YAML Data Types?
YAML supports 6 native scalar types: strings, integers, floats, booleans, null, and dates. The parser detects the type automatically based on the value's format, which is useful but can cause unexpected behavior if you're not careful.
Strings
Strings are the most flexible type in YAML. They don't require quotes in most cases. But there are situations where quoting is mandatory.
When you must quote a string:
-
The value starts with a special character (
:,{,},[,],,,#,&,*,?,|,>,!,%,@,`) -
The value could be misread as another type (
"true","null","1.0") -
The value contains a colon followed by a space
Single quotes preserve the literal string exactly. Double quotes allow escape sequences like \n (newline) and \t (tab).
plain: This is a plain string
single: 'Literal backslash: \n stays as \n'
double: "Escape works here: \n becomes a newline"
Numbers and Booleans
Integers are written as bare numbers: 42, -7, 0.
Floats follow standard decimal notation: 3.14, -0.5, 1.0e3.
Booleans accept true and false. Here's the tricky part: YAML 1.1 (still used by PyYAML, which is common) also treats yes, no, on, off as booleans. YAML 1.2 removed that behavior, but parser inconsistency means you shouldn't rely on it either way.
The "Norway Problem" is real. The country code NO parses as boolean false in YAML 1.1 parsers. Always quote country codes and similar values.
count: 42
ratio: 0.75
enabled: true
country: "NO" # quoted to prevent boolean coercion
Null and Date Values
Null is represented as null or the tilde ~. An empty value also resolves to null.
Dates follow ISO 8601 format. An unquoted 2024-01-15 becomes a date object in many parsers, not a string. Wrap it in quotes if you need it as text.
missing: null
also_missing: ~
bare_missing:
date_object: 2024-01-15
date_string: "2024-01-15"
How Does YAML Indentation and Syntax Work?
Indentation defines structure in YAML. There are no closing tags, no brackets to match. The hierarchy comes entirely from how far each line is indented.
The single hardest rule for most people new to YAML: spaces only, never tabs. A single tab character will throw a ScannerError. Most editors handle this automatically, but Vim users running default settings have hit this more than once.
The Core Syntax Rules
2-space indentation is the community standard. 4-space works. What matters is consistency within a file.
Key syntax elements:
-
Key-value pairs use a colon and a space:
key: value -
Comments start with
#and can appear inline after a value -
Document start marker is
---(optional but conventional) -
Document end marker is
...(optional, used in streaming contexts) -
YAML is case-sensitive:
True,true, andTRUEbehave differently in some parsers
---
# This is a comment
app_name: my-service # inline comment
port: 8080
debug: true
Indentation Errors in Practice
Nearly 40% of developers have encountered parsing failures from indentation mistakes, according to Stack Overflow survey data cited by MoldStud.
That number makes sense. A single misplaced space shifts everything below it in the hierarchy. There's no closing bracket to catch the error visually. You often don't find out until the parser runs.
Use yamllint or the Red Hat YAML extension for VS Code to catch these before they cause problems. Both tools flag indentation issues immediately.
What Is the YAML Scalar Syntax?
A scalar is any single value in YAML. Strings, numbers, booleans, and dates are all scalars. The format gives you 3 distinct ways to write them, each with different behavior for whitespace and newlines.
Literal Block Scalar (|)
The pipe character preserves newlines exactly as written. Each newline in the block becomes a newline in the output. Useful for embedding shell scripts, certificates, or any content where line breaks matter.
script: |
#!/bin/bash
echo "Starting deployment"
cd /app && npm start
Chomping indicators control trailing newlines:
-
|keeps one trailing newline (default) -
|-strips all trailing newlines -
|+keeps all trailing newlines
Folded Block Scalar (>)
The > character folds newlines into spaces. Single line breaks inside the block become spaces. Blank lines become actual newlines. Good for long strings that need to stay readable in the YAML file but exist as a single line in the output.
description: >
This is a long description
that wraps across multiple lines
but becomes one line in output.
The output of the above is: This is a long description that wraps across multiple lines but becomes one line in output.\n
Quoted Scalars
Single-quoted and double-quoted scalars sit on one line (unless deliberately continued). Double quotes support escape sequences. Single quotes don't.
|
Style |
Escape sequences |
When to use |
|---|---|---|
|
Plain |
No |
Simple values with no special characters |
|
Single |
No |
Values where |
|
Double |
Yes |
Values needing |
|
Literal |
N/A |
Multiline content, preserve newlines |
|
Folded |
N/A |
Multiline content, fold to single line |
How Are YAML Mappings (Key-Value Pairs) Written?
Mappings are the fundamental YAML structure. A mapping is a collection of key-value pairs where each key is unique within its scope. Most YAML files you'll ever work with are primarily made up of mappings.
Basic and Nested Mappings
The basic form is one key-value pair per line:
name: my-app
version: "1.0.0"
port: 3000
Nested mappings use indentation to create parent-child relationships:
database:
host: localhost
port: 5432
name: production_db
credentials:
user: admin
password: "secret"
database is the parent key. host, port, name, and credentials are its children. credentials is itself a mapping with two children.
Flow Mappings
Flow mappings write key-value pairs on a single line using curly braces. Functionally identical to block mappings. Better for short, simple structures where vertical space matters.
server: {host: localhost, port: 8080, debug: false}
Merging Mappings With <<
The merge key (<<) lets one mapping inherit the key-value pairs of another. Commonly used with anchors.
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
host: prod.example.com
production inherits timeout and retries from defaults, then adds its own host. The merge key reduces repetition across similar config blocks. It's especially useful in Docker Compose files where multiple services share base configurations.
Limitation: Merge keys are file-scoped. They cannot pull from another YAML file.
How Are YAML Sequences (Lists) Written?
A sequence is an ordered list of items. Unlike mappings, items don't have unique keys. The position in the list is what matters.
59% of professional developers use Docker (Stack Overflow, 2024), and Docker Compose sequences are where most people first encounter YAML lists in production configs.
Block Sequences
Each item in a block sequence starts with a dash and a space (- ). The dash is part of the indentation.
services:
- api
- worker
- scheduler
Common mistake: forgetting that the dash counts as part of the indentation. This breaks:
app:
name: my-app
services:
- api # wrong: not indented under anything
Flow Sequences
Flow sequences use square brackets. Inline. Good for short lists of simple values.
ports: [3000, 8080, 9090]
tags: ["web", "production", "v2"]
Sequences of Mappings
This is the pattern used in Kubernetes pod specs, GitHub Actions steps, and Ansible tasks. Each list item is itself a mapping.
steps:
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Deploy
run: ./deploy.sh
env:
NODE_ENV: production
Each item starts with - followed by the first key of that item's mapping. Subsequent keys in the same item are aligned with the first key, not the dash.
What Are YAML Anchors and Aliases?
Anchors and aliases are YAML's built-in mechanism for reusing content. Define a block once, reference it anywhere else in the same file. No duplication, no drift between repeated sections.
Over 93% of professional teams track configuration files in Git (Stack Overflow 2024, cited by MoldStud). Anchors reduce the lines that need tracking in the first place.
Anchor and Alias Syntax
Anchor: &anchor_name marks a reusable block.
Alias: *anchor_name inserts the anchored block in its place.
base_config: &base
image: node:18-alpine
restart: unless-stopped
environment:
NODE_ENV: production
api:
<<: *base
ports:
- "3000:3000"
worker:
<<: *base
command: node worker.js
Both api and worker inherit from base_config. If you change the base image, you change it once. Both services pick it up.
Extending With the Merge Key
The << merge key inserts the aliased content and allows the receiving mapping to override specific keys.
defaults: &defaults
replicas: 1
memory: 256Mi
api:
<<: *defaults
replicas: 3 # overrides the anchor value
memory: 512Mi # overrides the anchor value
2 hard limits to know:
-
Anchors are file-scoped.
*basefromfile-a.yamlcannot be referenced infile-b.yaml. -
Circular anchors are not allowed. An anchor cannot reference itself.
GitHub Actions uses anchors heavily in complex workflow files to share step definitions across jobs. Ansible playbooks use the same pattern for shared task variables.
How Do YAML Multi-Document Files Work?
A single .yaml file can contain multiple separate YAML documents, each divided by ---. This is standard practice in Kubernetes, where a Deployment and its Service often ship in one file.
The --- marker signals the start of a new document. The ... marker signals an explicit end. Both are optional in most contexts, but --- at the top of every document is a widely followed convention.
Separating Documents With ---
Standard multi-document layout:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
---
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- port: 80
kubectl apply -f processes both documents in one command. Tools like ArgoCD and Helm read every resource in a multi-document file and track them as a single application.
Parser Support for Multi-Document Files
Not all parsers handle multi-document YAML automatically.
Behavior by tool:
-
kubectl: Reads all documents in a file natively
-
PyYAML: Requires
yaml.safe_load_all(), notyaml.safe_load() -
Terraform: The
yamldecode()function fails on multi-document files (known issue) -
js-yaml: Supports multi-document via
loadAll()
The ... end-of-document marker matters most in streaming contexts. YAML parsers processing a continuous data stream use it to know when one document ends and the next hasn't started yet.
What Are the Most Common YAML Errors and How to Fix Them?
Over 70% of issues in YAML configuration files stem from indentation problems, according to MoldStud's analysis of YAML parsing failures. The format's reliance on whitespace makes it unusually sensitive to mistakes that would be invisible in other formats.
Tab vs. Space Errors
Tabs are illegal in YAML. A single tab character throws a ScannerError that looks like this:
yaml.scanner.ScannerError: mapping values are not allowed here
The error message rarely says "tab detected." It just points to the line where the parser got confused, which is usually one or two lines after the actual tab.
Fix: Set your editor to insert spaces automatically. In VS Code, the YAML extension from Red Hat catches this immediately. yamllint flags it before runtime.
Missing Space After Colon
key:value is not valid YAML. key: value is.
The colon-space combination is the delimiter. Without the space, the parser treats the entire string as a plain scalar, not a key-value pair.
# Wrong
port:8080
# Right
port: 8080
Boolean and Type Coercion Issues
A 2024 survey found 35% of YAML parsing issues stem from incorrect string declaration, according to MoldStud research.
|
Value |
YAML 1.1 result |
YAML 1.2 result |
Safe fix |
|---|---|---|---|
|
|
Boolean |
String |
Quote it: |
|
|
|
String |
Quote it: |
|
|
Float |
Float |
Quote it: |
|
|
Date object |
Date object |
Quote it: |
Unquoted Special Characters
Several characters have reserved meaning in YAML when unquoted: :, #, {, }, [, ], ,, &, *, ?, |, >, !, %, @.
A value starting with any of these needs quotes. The most common offender is : inside a URL.
# Wrong
url: https://example.com/api
# Right
url: "https://example.com/api"
Wrong Nesting Level
Shifting a block one indentation level too deep or too shallow creates a completely different data structure with no error. The parse succeeds, but the data is wrong.
Validate with yamllint or use the YAML Validator to catch structural issues before they reach a runtime environment.
How Does YAML Compare to JSON and TOML?
YAML, JSON, and TOML each have a clear domain where they work best. No single format wins across all use cases.
YAML is a superset of JSON. Every valid JSON file is also valid YAML. You can feed {"key": "value"} to any YAML parser and it will parse correctly.
|
Dimension |
YAML |
JSON |
TOML |
|---|---|---|---|
|
Comments |
Yes |
No |
Yes |
|
Multiline strings |
Native |
Requires |
Native |
|
Type coercion |
Implicit (risky) |
Explicit (safe) |
Explicit (safe) |
|
Parser speed |
Slower |
Fastest |
Middle |
|
Deep nesting |
Clean |
Bracket-heavy |
Gets messy |
|
Best for |
DevOps config, IaC |
APIs, data exchange |
Flat app config |
YAML vs. JSON
JSON has no comment syntax. That's the dealbreaker for configuration files, where you need to explain why a value is set a certain way.
JSON also requires quoting every key, uses brackets everywhere, and has no multiline string support without escape sequences.
JSON parsers are significantly faster than YAML parsers. For API payloads processed at scale, JSON wins on performance. A RESTful API returning thousands of responses per second doesn't belong in YAML.
YAML vs. TOML
TOML is excellent for flat, human-written configuration. Rust's Cargo.toml, Python's pyproject.toml, and Hugo's config files all use it.
TOML avoids YAML's implicit type coercion entirely. yes is always the string "yes", never a boolean. That removes an entire category of bugs.
TOML gets messy with deep nesting. A 5-level Kubernetes resource structure would be painful to express in TOML but is natural in YAML.
What Are the YAML Tags and Custom Types?
YAML's !! prefix forces explicit type assignment. You use it when the parser's auto-detection would produce the wrong type, or when a specific application needs a custom type.
Tags follow the format !!type_name. Standard YAML tags cover all 6 native types. Language-specific tags extend beyond that.
Standard !! Tags
Built-in YAML type tags:
-
!!strforces a value to string:!!str 123→"123", not integer123 -
!!intforces integer parsing -
!!floatforces float parsing -
!!boolforces boolean interpretation -
!!nullforces null regardless of value -
!!seqforces sequence (list) type -
!!mapforces mapping (dict) type
The most common use case is preventing date auto-detection: !!str 2024-01-15 stays as a string.
Python-Specific Tags in PyYAML
PyYAML adds !!python/object tags that serialize arbitrary Python objects to YAML. Real Python's documentation shows the !! prefix is how YAML resolves "potential ambiguities" by casting values to specific data types.
# Standard type override
port: !!str 8080
enabled: !!str true
date: !!str 2024-01-15
# Python-specific (PyYAML only)
custom: !!python/object:mymodule.MyClass
attr: value
YAML 1.1 vs. YAML 1.2 Type Resolution
YAML 1.2 tightened implicit type resolution significantly. In YAML 1.1, yes, no, on, off, true, false all resolve to booleans. YAML 1.2 limits booleans to true and false only.
PyYAML still implements YAML 1.1 by default, which catches many developers off guard. The ruamel.yaml library supports YAML 1.2 if you need strict compliance.
How Is YAML Used in Real-World DevOps Tools?
YAML is the primary configuration language for the tools that run modern software development infrastructure. Understanding how each tool uses it differently saves real debugging time.
Ansible is the most widely used configuration management tool, according to Stack Overflow's 2024 Developer Survey. Docker is used by 59% of professional developers (Stack Overflow, 2024). Kubernetes production deployments jumped from 66% to 80% of organizations between 2023 and 2024 (CNCF). GitHub Actions runs over 5 million workflows every day.
Every one of those tools runs on YAML files.
Kubernetes Manifests
Every Kubernetes resource is defined as a YAML document. The structure is always the same: 4 top-level keys.
apiVersion: apps/v1 # API group and version
kind: Deployment # Resource type
metadata: # Name, namespace, labels
name: my-app
namespace: production
spec: # Desired state
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:v1.2.0
ports:
- containerPort: 3000
apiVersion and kind together determine which Kubernetes API handles the resource. metadata.name must be unique within a namespace. spec is where all the behavior lives.
Docker Compose Files
Docker Compose uses YAML to define multi-container applications. The top-level keys are services, volumes, and networks.
version: "3.9"
services:
api:
image: node:18-alpine
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://db:5432/app
depends_on:
- db
db:
image: postgres:15
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
depends_on controls startup order. volumes maps host paths or named volumes into containers. The YAML Formatter can clean up Compose files that have accumulated inconsistent spacing across edits.
GitHub Actions Workflows
GitHub Actions workflows live in .github/workflows/ and trigger on GitHub events. The continuous integration pipeline below runs on every push to main.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install
run: npm ci
- name: Test
run: npm test
on defines triggers. jobs contains one or more jobs. Each job has steps, which are either uses (a pre-built action) or run (a shell command). The workflow YAML maps directly to the build pipeline stages most teams already use.
Ansible Playbooks
Ansible playbooks are YAML files that define what should happen on remote hosts. The format uses a sequence of plays, each targeting specific hosts and running a list of tasks.
---
- name: Deploy web application
hosts: webservers
become: yes
vars:
app_version: "2.1.0"
tasks:
- name: Install Node.js
package:
name: nodejs
state: present
- name: Copy application files
copy:
src: ./app/
dest: /var/www/app/
- name: Start application service
service:
name: myapp
state: started
enabled: yes
hosts targets an inventory group. become: yes runs tasks with elevated permissions. vars sets playbook-level variables. Each task in the tasks sequence calls an Ansible module by name.
The indentation here is load-bearing. A task indented one level too far becomes a subtask of the task above it, not a sibling. Most Ansible debugging sessions eventually come back to a nesting problem.
If you need to convert between formats, the YAML to JSON Converter and JSON to YAML Converter handle both directions cleanly. For related reference material, the Docker cheat sheet and Kubernetes cheat sheet cover the commands that work alongside these YAML configs.
FAQ on YAML
What does YAML stand for?
YAML stands for "YAML Ain't Markup Language." The name is recursive. It was originally called "Yet Another Markup Language," but the creators renamed it to emphasize that YAML is a data serialization format, not a document markup system like HTML or XML.
What is the difference between YAML and JSON?
YAML supports comments, multiline strings, and anchors. JSON does not. YAML is also a superset of JSON, meaning valid JSON is valid YAML. For configuration files, YAML wins on readability. For API responses and data transfer, JSON is faster to parse.
Why does YAML use spaces instead of tabs?
The YAML specification prohibits tabs entirely. Parsers treat tab characters as illegal, throwing a ScannerError. Spaces create consistent, predictable indentation across all editors and environments. Nearly 40% of YAML errors come from indentation mistakes, most involving tabs.
What is a YAML anchor?
An anchor (&name) marks a reusable block of YAML. An alias (*name) references it elsewhere in the same file. This removes repetition in config files. The << merge key lets a mapping inherit anchor values while still overriding specific keys.
How do you write a multiline string in YAML?
Use | (literal block scalar) to preserve newlines exactly. Use > (folded block scalar) to fold line breaks into spaces. Add - after either symbol to strip trailing newlines. Multiline strings are common in Kubernetes pod specs and Ansible task definitions.
What are the YAML data types?
YAML supports six native scalar types: strings, integers, floats, booleans, null, and dates. The parser detects types automatically based on value format. Quote values like "true" or "2024-01-15" to prevent type coercion from converting them into booleans or date objects.
What is the difference between .yml and .yaml?
Nothing functional. Both extensions refer to the same format and are fully interchangeable. Most tools accept either. The YAML specification does not prefer one over the other. Docker Compose defaults to docker-compose.yml. GitHub Actions expects files under .github/workflows/ with either extension.
How do you validate a YAML file?
Use yamllint from the command line for syntax and style checks. The Red Hat YAML extension for VS Code validates in real time as you type. Online tools like the YAML Validator catch structural errors without any local setup required.
What is YAML used for in Kubernetes?
Every Kubernetes resource is defined in a YAML manifest. The file specifies apiVersion, kind, metadata, and spec. Kubernetes reads the desired state from the manifest and reconciles the cluster to match it. Production Kubernetes deployments reached 80% of organizations in 2024, per CNCF data.
How do you convert YAML to JSON?
Any valid YAML can be converted to JSON since YAML is a superset of JSON. Command-line tools like yq handle conversion directly. The YAML to JSON Converter works in the browser. The reverse is also possible using the JSON to YAML Converter.