YAML
The human-friendly data serialization language that became the lingua franca of modern infrastructure — the format behind Kubernetes manifests, Ansible playbooks, CI pipelines, and countless configuration files.
Created by Clark Evans, Ingy döt Net, and Oren Ben-Kiki
YAML — a recursive acronym for “YAML Ain’t Markup Language” — is a human-friendly data serialization language designed so that structured data reads almost like a plain-text outline. Proposed by Clark Evans in 2001 and designed with Ingy döt Net and Oren Ben-Kiki, YAML uses indentation, dashes, and colons instead of brackets and quotes to represent the mappings, sequences, and scalars common to virtually every programming language. A quarter of a century later it has become something its creators did not quite anticipate: the configuration language of modern infrastructure. Kubernetes manifests, Ansible playbooks, Docker Compose files, GitHub Actions workflows, and OpenAPI definitions are all written in YAML — meaning much of the world’s cloud infrastructure is, in a literal sense, described in YAML documents.
History & Origins
YAML emerged from the SML-DEV mailing list, a community formed around simplifying XML. In May 2001, Clark Evans posted a first draft of a new format, joined by Ingy döt Net (who had been working on a plain-text serialization module for Perl) and Oren Ben-Kiki. The acronym originally stood for “Yet Another Markup Language”, a tongue-in-cheek nod to the era’s proliferation of markup languages; between December 2001 and April 2002 it was repurposed as the recursive “YAML Ain’t Markup Language” to emphasize a crucial distinction — YAML is for data, not documents.
The design brief was explicit and ranked. The specification lists YAML’s goals in decreasing priority: be easily readable by humans; be portable between programming languages; match the native data structures of dynamic languages; support generic tools, one-pass processing, and extensibility; and be easy to implement. Human readability first — everything else second — is the single decision that explains both YAML’s enormous popularity and most of its criticisms.
After three years of refinement on the yaml-core mailing list, YAML 1.0 was finalized on January 29, 2004, followed by YAML 1.1 on January 18, 2005. Adoption came quickest in the dynamic-language world the format was designed to serve: Ruby 1.8 bundled the Syck YAML library in 2003, Rails made database.yml and YAML fixtures part of every project, and Python’s PyYAML became a ubiquitous dependency.
Design Philosophy
YAML’s syntax reflects a synthesis of ideas from earlier technologies — the specification itself notes that YAML builds upon concepts from C, Java, Perl, Python, Ruby, HTML, MIME, XML, SAX, and (in 1.2) JSON:
- Data types from Perl and friends. YAML’s three building blocks — mappings (hashes/dictionaries), sequences (arrays/lists), and scalars (strings, numbers, booleans) — mirror the native structures of Perl, Python, and Ruby, so a parsed document lands directly in idiomatic data structures.
- Structure from indentation. Like Python, YAML uses indentation for scope instead of braces or end-tags, which removes most of the syntactic noise that makes XML and JSON tiring to read and write by hand.
- Documents over streams. A YAML stream can contain multiple documents separated by
---, and comments (#) are first-class — two features JSON lacks that matter enormously for configuration files. - Progressive complexity. The common subset is learnable in minutes, but the full language includes anchors and aliases (
&/*) for reusing nodes, tags (!!type) for explicit typing, and flow style — JSON-like inline syntax — for compactness.
What YAML Looks Like
| |
Indentation defines nesting, - introduces sequence items, &/* let one node reference another, and the > folded scalar turns an indented block into a single flowed string. The same data could be written in flow style — {invoice: 34843, date: 2001-01-23, ...} — which is why, since YAML 1.2, JSON documents are also valid YAML.
Key Features
| Area | Capabilities |
|---|---|
| Data model | Mappings, sequences, and scalars, composable to any depth |
| Styles | Block style (indentation-based) and flow style (JSON-like inline) |
| Multi-line strings | Literal (|) and folded (>) block scalars with fine-grained control over line breaks |
| Reuse | Anchors (&), aliases (*), and merge keys reduce repetition within a document |
| Typing | Implicit type resolution via schemas, plus explicit tags like !!str and application-defined tags |
| Multiple documents | A single stream can carry many documents separated by --- and terminated by ... |
| Comments | Full-line and end-of-line comments with # — a decisive advantage over JSON for configuration |
| JSON compatibility | YAML 1.2 was designed as a strict superset of JSON |
The Norway Problem and Other Sharp Edges
YAML’s readability-first design created famous pitfalls. Under YAML 1.1’s implicit typing rules, unquoted yes, no, on, and off resolve to booleans — so a list of country codes containing NO (Norway) silently becomes false, a failure mode well known enough to have a name: the Norway problem. Similarly, an unquoted version number like 3.10 may parse as the float 3.1. YAML 1.2’s core schema dropped most of these rules, but many widely deployed parsers retained 1.1-era behavior for years, so the pitfalls persisted long after the spec fixed them.
Other recurring criticisms include the significance of invisible whitespace, the sheer size of the full specification relative to the simplicity of typical use, and security: generic deserialization features in some libraries could instantiate arbitrary objects from untrusted input, which is why modern APIs push safe-loading defaults. These critiques spawned deliberate reactions — StrictYAML rejects implicit typing outright, and NestedText strips the concept down to strings-only — while TOML positioned itself as a minimal alternative for configuration.
Evolution
The most consequential shift in YAML’s history was its convergence with JSON. The two formats were developed independently, but after YAML 1.1 the community recognized that JSON was already almost a subset of YAML. YAML 1.2 (July 21, 2009) made the relationship official, with the spec’s primary focus being to make YAML a strict superset of JSON, while pruning the implicit-typing rules that caused the most surprises.
The specification then sat unchanged for over a decade while adoption exploded. Around 2020 a new YAML Language Development Team began meeting regularly, and on October 1, 2021 it published YAML 1.2.2 — a substantially rewritten, clarified edition of the 1.2 spec intended as the first step in a renewed development process, alongside a public test suite to drive implementation consistency.
Meanwhile the ecosystem matured around a common core: libyaml (C), PyYAML and ruamel.yaml (Python), SnakeYAML (Java), go-yaml (Go), yaml (JavaScript), and serde-yaml (Rust) made YAML available essentially everywhere, and command-line tools like yq became the jq of YAML.
Current Relevance
YAML’s status today is a paradox: it is simultaneously one of the most-written languages in software and one that almost nobody set out to learn. The cloud-native era made it unavoidable — Kubernetes chose YAML for its manifests, Ansible for its playbooks, Docker Compose for its service definitions, and nearly every major CI system (GitHub Actions, GitLab CI, CircleCI, Azure Pipelines) for its pipeline definitions. The phrase “YAML engineer” exists as an only-half-joking job description, and entire tool categories — Helm, Kustomize, yq, yamllint — exist to generate, patch, query, and validate YAML at scale.
The language remains under active stewardship by the YAML Language Development Team, with the 1.2.2 revision, an official test suite, and ongoing work toward future versions. Whatever its critics say — and the criticisms are real — no replacement has displaced it from the center of infrastructure configuration.
Why It Matters
YAML won an argument that XML seemed to have settled: that data interchange formats should be optimized for the humans who read and write them, not just the machines that parse them. That bet made YAML the natural choice when the DevOps movement needed a way for people to declare infrastructure — and in doing so, YAML quietly became the surface syntax of declarative operations, the layer where humans meet Kubernetes clusters, automation runs, and build pipelines. Its sharp edges taught the industry equally durable lessons about the cost of implicit behavior, lessons visible in every successor format that chose strictness over convenience. Few languages with no functions, no loops, and no logic have shaped daily software practice as much: YAML matters because, in the 2020s, describing a system in YAML is how much of the industry programs its infrastructure.
Timeline
Notable Uses & Legacy
Kubernetes
Every Kubernetes resource — Deployments, Services, ConfigMaps — is conventionally declared in YAML manifests applied with kubectl, making YAML the primary interface to the world's dominant container orchestrator.
Ansible
Red Hat's automation platform expresses playbooks, roles, and inventories in YAML, so entire data-center configurations are described in YAML documents rather than code.
Docker Compose
Multi-container applications are defined in a compose.yaml file that declares services, networks, and volumes — one of the most widely written YAML files in development workflows.
GitHub Actions
CI/CD workflows live in .github/workflows/*.yml files; GitLab CI (.gitlab-ci.yml) and CircleCI follow the same pattern, making YAML the standard language of build pipelines.
OpenAPI Initiative
The OpenAPI Specification for describing REST APIs accepts definitions in YAML or JSON, and YAML is the format most commonly used for hand-authored API documents.
Home Assistant
The popular open-source home automation platform uses configuration.yaml and YAML-based automations as its primary configuration mechanism for a user base that reportedly exceeds a million active installations.
Language Influence
Influenced By
Influenced
Running Today
Run examples using the official Docker image:
docker pull mikefarah/yq:latestExample usage:
docker run --rm -v $(pwd):/workdir mikefarah/yq '.name' config.yaml