Skip to main content
C
CodeUtil

Config Files: My Honest Opinion After Years of YAML Debugging

I've debugged YAML indentation at 2am more times than I want to admit. Here's what I've learned about choosing the right config format for your project.

2025-04-1715 min
Related toolTOML Formatter

Use the tool alongside this guide for hands-on practice.

Why your config format choice actually matters

I used to think config format debates were bikeshedding. Then a YAML tab-vs-space issue caused a 3-hour outage on a client project at Šikulovi s.r.o. Now I have strong opinions.

The format you choose affects how often your team will break things, how easy configs are to review in PRs, and how much time you'll spend debugging invisible characters. Let me share what I've learned the hard way.

What makes a good configuration format

Configuration files have specific requirements that differ from data interchange formats. Before comparing TOML, YAML, and JSON, consider what properties matter most for configuration.

  • Human readability: Configs are edited by people, not just machines
  • Comment support: Explaining why a setting exists is often essential
  • Error resistance: Syntax should minimize mistakes during manual editing
  • Type clarity: It should be obvious whether a value is a string, number, or boolean
  • Tooling support: Editors, validators, and parsers should be widely available
  • Simplicity: Fewer features mean fewer ways to create confusing configurations
  • Hierarchical data: Nested settings should be easy to represent and read

TOML: Tom's Obvious Minimal Language

TOML was designed specifically for configuration files. Created by Tom Preston-Werner (GitHub co-founder), it prioritizes being obvious to read and write. TOML aims to map clearly to a hash table structure.

  • Syntax: key = value pairs, [sections], [[array of tables]]
  • Comments: # for single-line comments anywhere in the file
  • Strings: Basic ("...") and literal ('...') with multiline variants
  • Numbers: Integers, floats, with optional underscores (1_000_000)
  • Booleans: true and false (lowercase only)
  • Dates: Native support for dates, times, and datetimes (2026-01-22T10:30:00Z)
  • Used by: Rust (Cargo.toml), Python (pyproject.toml), Hugo, many modern tools

TOML syntax example

A typical TOML configuration file shows the format's clarity and structure.

  • title = "My Application" — Simple key-value at the top level
  • [database] — Section header groups related settings
  • host = "localhost" — String value within section
  • port = 5432 — Integer value, no quotes needed
  • enabled = true — Boolean value
  • [[servers]] — Array of tables for multiple similar items
  • Each [[servers]] block creates a new server entry

YAML: YAML Ain't Markup Language

YAML uses indentation to represent hierarchy, similar to Python. Originally meaning "Yet Another Markup Language," it was renamed to emphasize data over documents. YAML is a superset of JSON, meaning valid JSON is valid YAML.

  • Syntax: Indentation-based hierarchy, key: value pairs
  • Comments: # for single-line comments
  • Strings: Usually unquoted, but quoted when needed
  • Numbers: Integers and floats recognized automatically
  • Booleans: yes/no, true/false, on/off all valid (can cause issues)
  • Null: null, ~, or empty value
  • Used by: Kubernetes, Docker Compose, Ansible, GitHub Actions, CI/CD configs

YAML syntax example

YAML configuration relies on consistent indentation to define structure.

  • title: My Application — Unquoted strings are common
  • database: — Parent key with nested children
  • host: localhost — Two-space indent shows nesting
  • port: 5432 — Numbers parsed automatically
  • enabled: true — Boolean value
  • servers: — List indicated by dash prefix
  • - name: web1 — Each dash starts a list item

JSON: JavaScript Object Notation

JSON was derived from JavaScript object syntax. It is primarily a data interchange format but is often used for configuration, especially in JavaScript ecosystems. JSON's strict syntax makes it unambiguous but less human-friendly.

  • Syntax: {} for objects, [] for arrays, "key": value pairs
  • Comments: Not supported in standard JSON
  • Strings: Always double-quoted, including keys
  • Numbers: Integers and floats, no special formats
  • Booleans: true and false only
  • Null: null only
  • Used by: package.json (Node.js), tsconfig.json (TypeScript), VS Code settings

JSON syntax example

JSON configuration requires strict adherence to its syntax rules.

  • { — Opening brace required for object
  • "title": "My Application" — All strings double-quoted
  • "database": { — Nested objects use braces
  • "host": "localhost" — Every key quoted
  • "port": 5432 — Numbers unquoted
  • "enabled": true — Boolean lowercase
  • No trailing commas allowed after last item

Comment support comparison

Comments are essential for configuration files. They explain why settings exist, document acceptable values, and provide context for future maintainers.

  • TOML: Full comment support with # anywhere
  • YAML: Full comment support with # anywhere
  • JSON: No native comment support whatsoever
  • JSON5/JSONC: Extended JSON formats add comments, but are non-standard
  • Workarounds for JSON: "_comment" keys (ugly) or preprocessors
  • Comment-free configs lead to tribal knowledge and maintenance burden
  • For human-edited configs, comment support is nearly essential

Type handling and surprises

How each format handles types affects both clarity and potential for errors. Implicit type coercion can cause unexpected behavior.

  • YAML: "no" becomes false, "1.0" may become number — infamous gotchas
  • YAML: Norway problem — "NO" (country code) parses as false
  • YAML: Version "1.0" becomes float 1, breaking semver comparisons
  • TOML: Explicit types, quoted strings stay strings
  • JSON: Strict but limited — no date type, numbers can lose precision
  • JSON: Large integers (>53 bits) may lose precision in JavaScript
  • TOML native dates eliminate string-parsing for timestamps

YAML type coercion gotchas

YAML's implicit typing is its most controversial feature. Values that look like numbers, booleans, or nulls are automatically converted.

  • country: NO — Becomes boolean false, not string "NO"
  • version: 1.0 — Becomes float 1.0, not string "1.0"
  • password: 12345 — Becomes integer, not string
  • date: 2026-01-22 — Becomes date object, not string
  • Fix with quotes: country: "NO", version: "1.0"
  • YAML 1.2 reduced some issues but most parsers use YAML 1.1
  • Always quote strings that might be misinterpreted

Multiline strings

Configuration often includes long strings like certificates, SQL queries, or scripts. Each format handles multiline content differently.

  • TOML: Triple quotes for multiline — """text""" or '''literal'''
  • TOML: Backslash at line end joins lines without newline
  • YAML: | preserves newlines (literal block)
  • YAML: > folds newlines to spaces (folded block)
  • YAML: Indentation determines string boundaries
  • JSON: Escape newlines as \n within a single-line string
  • JSON: Arrays of strings sometimes used for readability (workaround)

Nested data structures

Configuration often requires hierarchical data — settings grouped by feature, environment, or component. Each format approaches nesting differently.

  • TOML: [section] and [section.subsection] for nesting
  • TOML: Deep nesting becomes verbose with repeated table names
  • YAML: Indentation naturally represents hierarchy
  • YAML: Deep nesting is compact but indentation errors are easy
  • JSON: Braces nest objects, clean but verbose
  • JSON: Closing braces pile up at the end
  • For shallow configs (2-3 levels), all work well; deep nesting favors YAML

Error resistance and debugging

Configuration errors cause outages. How easily can you spot mistakes in each format, and how helpful are error messages?

  • TOML: Strict parsing catches most errors early
  • TOML: Clear error messages with line numbers
  • YAML: Indentation errors are easy to make, hard to see
  • YAML: Tab vs space issues cause subtle failures
  • YAML: Copy-paste often breaks indentation
  • JSON: Missing commas and trailing commas cause failures
  • JSON: Syntax errors usually point to exact position

Tooling and editor support

Good tooling improves the editing experience with syntax highlighting, validation, autocompletion, and formatting.

  • JSON: Best tooling — universal support, JSON Schema validation
  • JSON: Every editor highlights and validates JSON
  • YAML: Good support but schema validation less common
  • YAML: Many editors struggle with complex YAML features
  • TOML: Growing support, excellent in Rust tooling
  • TOML: VS Code, JetBrains IDEs have good extensions
  • Schema support helps catch errors before runtime

File size and parsing performance

For most configuration files, size and parsing speed are negligible concerns. However, large configs or frequently parsed files may warrant consideration.

  • JSON: Most compact for data, fastest to parse
  • JSON: Optimized parsers available in all languages
  • TOML: Slightly larger due to section headers
  • TOML: Parsing speed is adequate for configuration
  • YAML: Most verbose due to indentation overhead
  • YAML: Complex features slow down parsing
  • For configs under 1MB, performance differences are irrelevant

When to use TOML

TOML excels for configuration files that prioritize clarity and correctness.

  • Project configuration: Cargo.toml, pyproject.toml, Go modules
  • Application settings where humans edit frequently
  • When explicit typing prevents errors (versions, dates)
  • Flat to moderately nested structures
  • When comments are essential for documentation
  • When avoiding YAML gotchas is important
  • Modern CLI tools and development environments

When to use YAML

YAML works well for complex, deeply nested configurations where its flexibility shines.

  • Kubernetes manifests and cloud infrastructure
  • CI/CD pipelines (GitHub Actions, GitLab CI, CircleCI)
  • Docker Compose and container orchestration
  • Ansible playbooks and automation scripts
  • When ecosystem conventions mandate YAML
  • Deeply nested structures that would be verbose in TOML
  • When teams are already familiar with YAML conventions

When to use JSON

JSON is appropriate when tooling and interoperability matter most.

  • Node.js ecosystem: package.json, tsconfig.json
  • Web application configuration with JSON Schema validation
  • Configuration that is machine-generated more than human-edited
  • When the configuration is also used as an API contract
  • VS Code settings and other tools requiring JSON
  • When strict parsing and universal compatibility are priorities
  • Environments where JSON5 or JSONC provide comment support

Migration considerations

Switching configuration formats requires updating tooling, documentation, and team habits.

  • Automated converters exist between all three formats
  • YAML and TOML can represent everything JSON can
  • JSON cannot represent YAML/TOML comments or date types
  • Test extensively after migration — type coercion may cause issues
  • Update documentation and development guidelines
  • Train team members on new format conventions
  • Consider gradual migration for large codebases

Best practices for any format

Regardless of format choice, these practices improve configuration management.

  • Validate configuration at application startup
  • Use schema validation where available (JSON Schema, etc.)
  • Document all settings with comments or external docs
  • Keep configuration DRY — avoid repetition
  • Use environment variables for secrets, not config files
  • Version control all configuration files
  • Provide sensible defaults to minimize required configuration

Quick comparison table

A summary of the key differences between TOML, YAML, and JSON for configuration files.

  • Comments: TOML ✓, YAML ✓, JSON ✗
  • Native dates: TOML ✓, YAML ✓, JSON ✗
  • Type safety: TOML (strict) > JSON (strict) > YAML (loose)
  • Nesting ease: YAML > JSON > TOML
  • Tooling maturity: JSON > YAML > TOML
  • Human editing: TOML ≈ YAML > JSON
  • Error resistance: TOML > JSON > YAML

Conclusion: Choose based on your needs

There is no universally "best" configuration format. TOML provides the best balance of readability, safety, and configuration-specific features. YAML handles complex nested structures well but requires discipline to avoid gotchas. JSON offers universal tooling but lacks human-friendly features.

For new projects with human-edited configuration, TOML is increasingly the recommended choice. For infrastructure and DevOps work, YAML's ecosystem dominance makes it practical. For JavaScript/TypeScript projects, JSON remains the standard despite its limitations. Use our TOML Formatter, YAML Converter, and JSON Formatter tools to work with any format.

FAQ

What is the main difference between TOML and YAML?

TOML uses [section] headers with explicit syntax. YAML uses indentation. TOML won't turn "no" into false. YAML handles deep nesting better but has more gotchas.

Why doesn't JSON support comments?

JSON was designed for machines, not humans. Crockford wanted it minimal. If you need comments, use JSONC or switch to YAML/TOML.

What is the YAML Norway problem?

"NO" becomes false in YAML. Norway's country code breaks your config. Always quote: country: "NO". I've seen this cause production bugs.

Which format is best for Kubernetes configuration?

YAML. The entire K8s ecosystem uses it. Don't fight convention - just be careful with indentation.

Can I convert between TOML, YAML, and JSON?

Yes, but you'll lose comments converting to JSON. YAML to TOML might expose type coercion issues. Test thoroughly after converting.

What is the difference between YAML 1.1 and YAML 1.2?

1.2 fixed many type coercion issues. Problem: most parsers still default to 1.1 behavior. Check your parser's config.

Is TOML better than YAML for configuration?

For human-edited configs, I prefer TOML - fewer gotchas. YAML only when the ecosystem requires it (K8s, CI/CD) or for deeply nested structures.

What tools validate TOML, YAML, and JSON files?

JSON Schema + ajv for JSON/YAML. TOML validators built into parsers. For quick checks, I use our tools at /toml, /yaml, and /json.

Martin Šikula

Founder of CodeUtil. Web developer building tools I actually use. When I'm not coding, I experiment with productivity techniques (with mixed success).

Related articles