YAML (YAML Ain't Markup Language) is the configuration format behind Docker Compose, Kubernetes, GitHub Actions, Ansible, and most CI/CD pipelines. It's readable, but it has sharp edges. Here's what you need to know.
Basic syntax
YAML uses indentation (spaces only — never tabs) to represent structure:
name: Alice
age: 30
active: true
score: 9.5
nothing: null
These map directly to JSON types: strings, numbers, booleans, null.
Strings
Strings don't need quotes — unless they contain special characters:
# These are all strings without quotes
name: Alice
message: Hello, world
path: /usr/local/bin
# Use quotes when the value would otherwise be misinterpreted
version: "1.0" # Without quotes: parsed as float 1.0, not string
flag: "true" # Without quotes: parsed as boolean true
colon: "key: value" # Without quotes: YAML parser error
empty: "" # Explicit empty string
Single quotes (') prevent escape sequences. Double quotes (") allow them:
literal: 'Line\nbreak' # stored as: Line\nbreak (backslash-n literal)
escaped: "Line\nbreak" # stored as: Line + newline + break
Multiline strings
# Literal block (|): preserves newlines
description: |
This is the first line.
This is the second line.
Newlines are preserved.
# Folded block (>): newlines become spaces
summary: >
This is a long description
that wraps across lines.
Output is one paragraph.
The | block is useful for scripts, SQL queries, or any content where line breaks matter. The > block is useful for long prose that should be treated as a single string.
Lists
# Block sequence
fruits:
- apple
- banana
- cherry
# Inline sequence
fruits: [apple, banana, cherry]
Objects / mappings
# Block mapping
address:
street: 123 Main St
city: London
postcode: SW1A 1AA
# Inline mapping
address: {street: 123 Main St, city: London}
Nested structures
users:
- name: Alice
role: admin
permissions:
- read
- write
- delete
- name: Bob
role: viewer
permissions:
- read
YAML vs JSON
YAML is a superset of JSON — every valid JSON document is valid YAML. YAML adds:
- Comments (
#) - Multiline strings
- No quotes required for strings
- Anchors and aliases for reuse
To convert between the two formats, the YAML to JSON Converter handles both directions and validates syntax.
The Norway problem and other gotchas
Boolean parsing
Different YAML parsers have different rules for implicit booleans. YAML 1.1 (used by many older parsers) treats these as booleans:
# YAML 1.1 — these are all booleans:
yes, no, on, off, true, false, y, n
country: NO # parsed as boolean false!
toggle: on # parsed as boolean true
YAML 1.2 (the current spec) only recognizes true and false as booleans. But many tools (PyYAML, Ruby's Psych) still use YAML 1.1 by default.
Fix: always quote values that look like booleans but aren't:
country: "NO"
toggle: "on"
Number parsing
port: 8080 # integer
ratio: 0.5 # float
hex: 0xFF # integer 255 (YAML 1.1)
octal: 0755 # integer 493 — dangerous! Looks like a permissions string
Version numbers and semver tags are particularly dangerous:
version: 1.10 # parsed as float 1.1 — not the string "1.10"!
version: "1.10" # correct: preserved as string
Indentation errors
YAML is whitespace-sensitive. Two spaces per level is conventional, but consistency within a file matters more than the number:
# Wrong: inconsistent indentation
servers:
- name: web
port: 80
- name: db # Error: this dash is at a different indent level
port: 5432
# Right
servers:
- name: web
port: 80
- name: db
port: 5432
Tabs are never valid in YAML for indentation. Most YAML errors are either tabs or inconsistent indent depth.
Anchors and aliases
YAML lets you define a value once and reuse it:
defaults: &defaults
timeout: 30
retries: 3
development:
<<: *defaults # merge all defaults
host: localhost
production:
<<: *defaults # merge again
host: prod.example.com
timeout: 60 # override one value
This is especially useful in Docker Compose for sharing service configuration and in CI/CD pipelines for shared job configuration.
Common use cases
GitHub Actions:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
Docker Compose:
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
Kubernetes deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
When to use YAML vs JSON
| Factor | YAML | JSON |
|---|---|---|
| Comments | Yes | No |
| Human writing | Easier | Verbose |
| Machine generation | Error-prone | Safer |
| Browser/JS native | Needs library | Native (JSON.parse) |
| Config files | Yes | Possible |
| API responses | Avoid | Preferred |
Use YAML for files humans edit (CI configs, Kubernetes manifests, application config). Use JSON for data exchange between programs.
YAML's strength is readability for humans writing configuration files. Its weakness is the implicit type coercion — things that look like strings silently become booleans or numbers. When in doubt, quote your strings, especially for version numbers, port numbers, country codes, and any value that overlaps with YAML's boolean keywords.
Top comments (0)