YAML ("YAML Ain't Markup Language") is the configuration language of modern DevOps. Kubernetes manifests, GitHub Actions workflows, Docker Compose files, Ansible playbooks — they all use YAML. This guide covers the syntax, common pitfalls, and the tricky edge cases that trip up even experienced developers.
YAML Basics
YAML uses indentation (spaces, never tabs) to represent structure. At its core, everything is either a mapping (key-value pair), a sequence (list), or a scalar (string, number, boolean).
# This is a comment
# Mapping (key: value)
name: DevBolt
url: https://devbolt.dev
port: 3000
# Sequence (list)
tools:
- JSON Formatter
- Base64 Encoder
- Hash Generator
# Nested mapping
database:
host: localhost
port: 5432
credentials:
user: admin
password: secretData Types
YAML auto-detects types. This is powerful but also the source of many bugs:
# Strings
name: hello # unquoted
name: "hello world" # double-quoted (supports escapes)
name: 'hello world' # single-quoted (literal)
# Numbers
count: 42 # integer
price: 19.99 # float
hex: 0xff # hexadecimal
octal: 0o755 # octal
# Booleans
enabled: true
disabled: false
# Null
value: null
also_null: ~
also_null_2: # empty value = null
# Dates
created: 2026-03-18
timestamp: 2026-03-18T14:30:00ZThe Norway Problem (and Other Type Gotchas)
YAML's auto-typing is its most notorious footgun. Country codes, version numbers, and other values can be silently interpreted as the wrong type:
# These are all interpreted as booleans (true/false):
country: NO # false (not the string "NO"!)
answer: yes # true
flag: off # false
confirm: on # true
# These are interpreted as numbers:
version: 1.0 # float 1.0 (not string "1.0")
zipcode: 01onal # octal 1 (not string "01")
build: 3.10 # float 3.1 (not string "3.10")
# Fix: always quote ambiguous values
country: "NO"
version: "1.0"
zipcode: "01234"
build: "3.10"This is called the Norway problem. The country code "NO" becomes boolean false. The fix is simple: quote any value that could be misinterpreted.
Multiline Strings
YAML has two multiline operators. This is one of its most useful features:
# Literal block (|) — preserves newlines exactly
script: |
#!/bin/bash
echo "Hello"
echo "World"
# Result: "#!/bin/bash\necho \"Hello\"\necho \"World\"\n"
# Folded block (>) — joins lines with spaces (like HTML)
description: >
This is a long
description that will
be folded into one line.
# Result: "This is a long description that will be folded into one line.\n"
# Strip trailing newline with "-"
script: |-
echo "no trailing newline"
# Result: "echo \"no trailing newline\""
# Keep trailing newlines with "+"
script: |+
line one
line two
# Result: "line one\nline two\n\n"Use | (literal) for shell scripts, SQL, and code where newlines matter. Use > (folded) for long descriptions and prose.
Anchors and Aliases
Avoid repetition with anchors (&) and aliases (*):
# Define an anchor
defaults: &defaults
timeout: 30
retries: 3
log_level: info
# Reuse with alias
development:
<<: *defaults
log_level: debug # override one value
production:
<<: *defaults
timeout: 60 # override one value
# Without anchors, you'd repeat all three values twiceThe << merge key injects all key-value pairs from the anchor. Any keys you define after the merge override the anchored values.
Multi-Document Files
A single YAML file can contain multiple documents, separated by ---. This is commonly used in Kubernetes:
# Document 1: Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
---
# Document 2: Service
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
ports:
- port: 80Flow Style (Inline Syntax)
YAML supports a compact JSON-like syntax for short values:
# Flow mapping (inline object)
point: {x: 10, y: 20}
# Flow sequence (inline array)
colors: [red, green, blue]
# Mixed
servers:
- {host: web1, port: 80}
- {host: web2, port: 80}
# Equivalent block style:
servers:
- host: web1
port: 80
- host: web2
port: 80Flow style is great for short, simple data. For anything complex, stick with block style for readability.
YAML vs JSON vs TOML
| Feature | YAML | JSON | TOML |
|---|---|---|---|
| Comments | Yes | No | Yes |
| Multiline strings | Yes (| and >) | No | Yes (triple quotes) |
| References/anchors | Yes | No | No |
| Readability | High | Medium | High |
| Parsing safety | Risky (type coercion) | Safe | Safe |
| Common use | K8s, CI/CD, Ansible | APIs, package.json | Cargo.toml, pyproject |
Real-World Examples
GitHub Actions Workflow
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm testDocker Compose
See our Docker Compose guide for a deep dive. Here's the basic structure:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
environment:
DATABASE_URL: postgres://user:pass@db:5432/appKubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myapp:1.2.3
ports:
- containerPort: 8080
resources:
limits:
memory: "256Mi"
cpu: "500m"Common Mistakes
- Using tabs for indentation. YAML only allows spaces. A single tab will cause a parse error. Configure your editor to insert spaces when you press Tab in YAML files.
- Not quoting ambiguous values. Values like
NO,yes,1.0,on, andoffare interpreted as booleans or numbers. Always quote strings that could be misinterpreted. - Inconsistent indentation. YAML doesn't mandate a specific indent size, but mixing 2-space and 4-space indentation in the same file will cause confusion (and often errors). Pick 2 spaces and stick with it.
- Duplicate keys. YAML silently allows duplicate keys — the last one wins. This can cause hard-to-find bugs when you accidentally define the same key twice in a large file.
- Forgetting the space after colons.
key:valueis a string, not a mapping. You need a space:key: value.
Running YAML in production?
If you're deploying Kubernetes manifests, DigitalOcean Kubernetes offers managed clusters with free control plane, automatic upgrades, and simple pricing. Great for teams that want K8s without the infrastructure overhead.
Try It Yourself
Use our YAML Validator & Formatter to validate and format your YAML files. Need to convert between formats? The JSON ↔ YAML Converter handles that instantly. And if you're working with Kubernetes, our Kubernetes YAML Validator checks for resource-specific issues beyond basic syntax.