← Back to Blog

TOML Explained: The Config Format That's Replacing YAML

March 9, 2026 8 min read By CodeTidy Team

If you've worked with Rust, modern Python packaging, or Hugo, you've encountered TOML — Tom's Obvious, Minimal Language. It's a configuration file format designed to be easy to read, unambiguous to parse, and impossible to get wrong in the subtle ways that YAML constantly trips people up.

TOML has been quietly gaining ground as the configuration format of choice for developer tools. Rust chose it for Cargo.toml. Python adopted it for pyproject.toml (PEP 518/PEP 621). Hugo, the static site generator, uses it. And the reasons why tell you a lot about what's wrong with YAML.

TOML Syntax in 5 Minutes

TOML looks like an INI file that grew up to support modern data types:

# This is a comment

title = "My Project"
version = "1.0.0"
enabled = true
max_retries = 3
pi = 3.14159

# Dates are first-class
created = 2026-03-09T10:30:00Z

# Arrays
tags = ["rust", "config", "toml"]

# Tables (objects/maps)
[database]
host = "localhost"
port = 5432
name = "myapp"

# Nested tables
[database.connection_pool]
min = 5
max = 20
timeout = 30

# Array of tables
[[servers]]
name = "alpha"
ip = "10.0.0.1"
role = "primary"

[[servers]]
name = "beta"
ip = "10.0.0.2"
role = "replica"

That's it. No indentation rules, no special characters that change meaning based on context, no "Norway problem." Every TOML file is unambiguously parseable.

Why TOML Over YAML?

YAML is the most popular configuration format, but it has well-documented problems:

The Norway Problem

# YAML
countries:
  - Norway    # Parsed as boolean false in YAML 1.1
  - France
  - DE        # Also parsed as boolean in some parsers

# TOML — no ambiguity
countries = ["Norway", "France", "DE"]

YAML 1.1 treats NO, no, Off, off, False, false (and their uppercase variants) as boolean false. Country codes like NO (Norway) and DE (Germany) can silently become booleans. YAML 1.2 fixed this, but many parsers still use YAML 1.1 semantics.

Indentation Sensitivity

# YAML — wrong indentation changes the structure
server:
  host: localhost
  port: 5432
   name: myapp    # One extra space = parse error or wrong nesting

# TOML — explicit structure, no indentation rules
[server]
host = "localhost"
port = 5432
name = "myapp"

Type Coercion Surprises

# YAML
version: 1.0     # Float, not string "1.0"
version: 1.10    # Float 1.1, not string "1.10"
phone: 12345678  # Integer, not string

# TOML — explicit types, no guessing
version = "1.0"
phone = "12345678"

In TOML, strings require quotes, numbers are numbers, booleans are true/false, and there's no automatic type coercion. You always know exactly what type a value is.

TOML vs JSON for Configuration

JSON works for configuration but has practical limitations:

  • No comments — JSON doesn't support comments, which is a dealbreaker for configuration files that need inline documentation
  • Trailing commas — JSON doesn't allow them, making editing error-prone
  • Verbose for nested structures — lots of braces and brackets for deeply nested configs
  • No date/time type — dates are just strings in JSON

TOML was explicitly designed to be a better JSON for config files: it has comments, dates, multi-line strings, and a syntax optimized for human readability.

Where TOML Is Used

ProjectFileWhy TOML
Rust / CargoCargo.tomlPackage metadata, dependencies, build config
Python (PEP 518/621)pyproject.tomlProject metadata, build system, tool config
Hugohugo.tomlSite configuration
Denodeno.json (supports TOML)Runtime configuration
PipenvPipfilePython dependency management
Black (Python formatter)pyproject.tomlFormatter settings
Ruff (Python linter)pyproject.tomlLinter configuration

Complete TOML Syntax Reference

Strings

# Basic strings (escape sequences work)
name = "Alice \"Wonderland\" Smith"
path = "C:\\Users\\alice"

# Literal strings (no escaping — use single quotes)
regex = 'C:\Users\.*'
winpath = 'C:\Users\alice'

# Multi-line basic strings
description = """
This is a
multi-line string.
Newlines are preserved."""

# Multi-line literal strings
code = '''
fn main() {
    println!("Hello, world!");
}
'''

Numbers

integer = 42
negative = -17
hex = 0xDEADBEEF
octal = 0o755
binary = 0b11010110

float = 3.14
scientific = 6.022e23
infinity = inf
not_a_number = nan

# Underscores for readability
large = 1_000_000
hex_color = 0xFF_AA_00

Dates and Times

# Offset date-time (RFC 3339)
created = 2026-03-09T10:30:00Z
updated = 2026-03-09T10:30:00-05:00

# Local date-time (no timezone)
meeting = 2026-03-09T14:00:00

# Local date
birthday = 1990-05-15

# Local time
alarm = 07:30:00

Tables and Nesting

# Standard table
[package]
name = "my-project"
version = "0.1.0"

# Dotted keys (inline nesting)
[package.metadata]
homepage = "https://example.com"

# Inline tables (for short tables)
point = { x = 1, y = 2 }

Arrays of Tables

# Each [[products]] creates a new element in an array
[[products]]
name = "Hammer"
price = 9.99

[[products]]
name = "Nail"
price = 0.05

# Equivalent JSON:
# {"products": [
#   {"name": "Hammer", "price": 9.99},
#   {"name": "Nail", "price": 0.05}
# ]}

Converting Between TOML and JSON

The mapping between TOML and JSON is straightforward:

# TOML
[server]
host = "localhost"
port = 5432
tags = ["primary", "production"]

[server.ssl]
enabled = true
cert = "/etc/ssl/cert.pem"
// Equivalent JSON
{
  "server": {
    "host": "localhost",
    "port": 5432,
    "tags": ["primary", "production"],
    "ssl": {
      "enabled": true,
      "cert": "/etc/ssl/cert.pem"
    }
  }
}

Use our TOML Formatter to format TOML files and convert between TOML and JSON bidirectionally.

TOML's Limitations

TOML isn't perfect for every use case:

  • Deeply nested structures get verbose — if your config is 5+ levels deep, the table header syntax becomes repetitive.
  • No schema language — unlike JSON Schema, there's no standardized way to validate TOML structure (though tools like taplo provide validation).
  • Less ecosystem support — JSON and YAML have parsers in every language. TOML support is good but not universal.
  • Not great for data interchange — TOML is designed for configuration, not for APIs or data serialization. Use JSON for that.

When to Use What

Use CaseBest FormatWhy
Application configTOMLReadable, typed, comments, no ambiguity
API responsesJSONUniversal support, fast parsing
Kubernetes manifestsYAMLEcosystem requirement (no choice)
Docker ComposeYAMLEcosystem requirement
CI/CD configYAMLGitHub Actions, GitLab CI require it
Package metadataTOMLCargo.toml, pyproject.toml set the standard

Need to format or convert TOML? Try our TOML Formatter & Converter — format, minify, and convert between TOML and JSON, all in your browser.

Drop file to load