Skip to content
datahacks.dev
YAML

Comments That Help the Next Person Reading Your YAML

What to write in YAML comments, what to leave out and how to lint comment style. Includes yamllint output for spacing and indentation, and what tools drop.

6 min read
Summarize in AI
Flat illustration of a tree of nested objects beside the document it came from, with the YAML logo.

Comments are the cheapest documentation a configuration file can have, and the only documentation that travels with the file. They are also the part nobody tests. A comment can be wrong for years, repeat what the line says or hold a password. This post is about what to write, what to leave out, how to keep the style consistent with a linter, and the few things that tools do to comments that you should know about.

What a good comment says

A configuration file already says what: the key name and the value. The reader's questions are why, what depends on this and can I change it. Good comments answer those:

YAML
timeout: 30        # the vendor API drops idle connections at 60s; keep well below
retries: 3         # raised from 2 after the March outage; each retry doubles delay
pool_size: 20      # must be <= max_connections / number_of_app_servers
# TODO(ana, 2026-12-01): remove once the old billing service is retired
legacy_billing: true

Each says something the line cannot: a constraint from outside the file, a reason from history, a relationship between settings, and a temporary state with an owner and a date. Compare the useless kind:

YAML
port: 5432         # PostgreSQL default
timeout: 30        # timeout in seconds
enabled: true      # enabled

These restate the key. They cost reading time, and they go stale: when the value changes, the comment may not. The test for a comment is whether deleting it would lose information. If not, delete it.

Four kinds are worth writing every time:

  1. Constraints and units that are not in the key name: # seconds, # must be <= max_connections, # bytes, not kilobytes.

  2. Reasons for non-default values. Why 30 and not the default 10.

  3. Warnings: what breaks if this changes, or what reads it. # read by the nightly job as well.

  4. Temporary state: a workaround, an experiment, a flag to remove, with an owner and a date.

A header comment at the top of the file says what it configures, who owns it, where its schema lives and how it is deployed. For files that are layered, say where this file sits in the order.

What to leave out

What the key already says. See above.

Commented-out configuration. Blocks of disabled settings drift from reality and confuse readers about which are live. Delete them; version control remembers. If you want to show an optional setting, write an example in documentation.

Secrets. A password in a comment is as exposed as one in a value. Same for personal data, internal host names and tokens. Scan comments with your secret scanner (keeping secrets out of YAML config files).

Information that a program needs. Comments are not data. They are dropped by yaml.safe_load and safe_dump, lost in conversion to JSON and ignored by every consumer. A flag such as "deprecated" must be a key.

Stale history. "Changed by Bob in 2019" belongs in git blame.

Style rules you can lint

Consistency makes comments easier to scan, and yamllint can enforce it. On this sample:

YAML
#no space after hash
a: 1 # one space before comment
b: 2  # two spaces
c: 3   #   many spaces
    # comment indented more than content
d: 4

with the comments rule set to require a starting space and two spaces before a trailing comment, and comments-indentation enabled:

Text
cm.yaml
  1:2       warning  missing starting space in comment  (comments)
  2:6       warning  too few spaces before comment: expected 2  (comments)
  5:5       warning  comment not indented like content  (comments-indentation)

Three findings: the first comment has no space after the hash, the second has one space before a trailing comment where two are required and the fifth line is a comment indented differently from the surrounding keys. The rules to consider:

  • comments: {require-starting-space: true} so every comment starts # text.

  • comments: {min-spaces-from-content: 2} for trailing comments, matching the common two-space style.

  • comments-indentation: enable so a comment sits at the indentation of the line it describes.

These produce warnings in the default configuration, so you can enforce them with --strict when you are ready. They do not judge content, only layout, and layout is what makes a file look uniform.

Where comments go

Put a comment above the key when it is long or applies to a block, and at the end of the line when it is short and about that value. A comment above a key is attached to that key by tools that preserve comments, and moves with it. A trailing comment stays on its line. In a list, put the comment above the item it describes. Do not put a comment between a key and its block scalar's content: inside a literal block a hash is text.

For a block of related settings, a comment above the first line is enough; do not repeat it. For a value that needs a long explanation, link to the document that has it instead of writing a paragraph: # see docs/runbooks/db-failover.md.

What tools do to comments

Comments survive in some tools and not in others, and that determines how you edit files:

  • yaml.safe_load then safe_dump in PyYAML drops every comment.

  • ruamel.yaml round-trip mode keeps comments and attaches them to nodes; deleting a key deletes its trailing comment, and a comment above the next key stays, which can leave an orphan that describes the wrong thing.

  • yq keeps comments, and normalizes the spacing before a trailing comment (three spaces became one in a test).

  • Conversion to JSON, CSV or any other format drops them.

So: files that humans edit and read are edited with a comment-preserving tool, and comments are not relied on by programs (comments in YAML and what parsers do with them has the tests).

Reviewing comments

Treat comments as part of the change. When a pull request changes a value, look at the comment on that line: does it still hold? A value moved from 30 to 60 with a comment saying "keep well below 60s" is a bug in the comment or the value. Ask for both to change together. Add a line to the pull request template: "Did you update comments that mention the values you changed?" It costs nothing, and it keeps the explanations true.

The cluster hub is structuring YAML configuration files that last. How parsers treat comments is in comments in YAML and what parsers do with them, and the checks around them in linting YAML with yamllint. The rules are documented in the yamllint comments rule and comment syntax in the YAML 1.2.2 specification. Reformat a file in the YAML formatter.

When comments are the wrong place for the information

A program must read it. Use a key.

It describes the whole system. Put it in documentation and link to it.

It changes often. A status that goes stale belongs in a tracker.

The file is generated. Comments written by hand vanish on regeneration. Document the generator.

Share

Keep reading

Get new articles by email

We send one email when a new article is published. No spam.

Unsubscribe in one click. No spam, ever.