TOML (Tom's Obvious Minimal Language)

Config files that are actually obvious—INI files evolved for the modern age.

4 min read

What is TOML?

TOML is a configuration file format that aims to be easy to read due to obvious semantics. Created by Tom Preston-Werner (co-founder of GitHub), it's designed to map unambiguously to a hash table.

toml
# This is a TOML document

title = "My Application"
version = "1.0.0"

[database]
host = "localhost"
port = 5432
enabled = true

[servers.alpha]
ip = "10.0.0.1"
role = "primary"

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

TOML takes the best parts of INI files and adds proper data types, nested tables, and arrays. Unlike YAML, it's impossible to shoot yourself in the foot with whitespace.

Basic Syntax

TypeTOMLNotes
Stringname = "hello"Double quotes required
Integerport = 8080Underscores allowed: 1_000_000
Floatpi = 3.14159Standard notation
Booleanenabled = trueLowercase only
Datedate = 2024-01-30ISO 8601 format
DateTimets = 2024-01-30T12:00:00ZWith time and timezone
Arrayports = [80, 443, 8080]Square brackets
Table[section]Creates a new section

Strings

TOML has four string types:

toml
# Basic string - escapes work
basic = "Hello\nWorld"

# Literal string - no escapes
literal = 'C:\Users\name'

# Multi-line basic
multiline = """
This spans
multiple lines.
"""

# Multi-line literal
multiline_literal = '''
Regex: \d+\.\d+
No escaping needed.
'''

Tables (Sections)

Tables are collections of key-value pairs:

toml
# Standard table
[server]
host = "localhost"
port = 8080

# Nested tables
[database.primary]
host = "db1.example.com"

[database.replica]
host = "db2.example.com"

# Inline table (for simple cases)
point = { x = 10, y = 20 }

Arrays

toml
# Simple array
colors = ["red", "green", "blue"]

# Multi-line array
dependencies = [
  "numpy",
  "pandas",
  "matplotlib",
]

# Array of tables (for repeated structures)
[[products]]
name = "Widget"
price = 9.99

[[products]]
name = "Gadget"
price = 19.99

The [[products]] syntax creates an array of tables—each section adds a new item to the products array.

Where You'll See This

  • Rust - Cargo.toml for package management
  • Python - pyproject.toml (PEP 518)
  • Go - go.mod influenced by TOML
  • Hugo - Static site configuration
  • InfluxDB - Database configuration
  • Netlify - netlify.toml for deployments

Common Gotchas

⚠️Table vs Array of Tables

[servers] creates a single table. [[servers]] creates an array of tables. Mixing them up causes confusing errors.

ℹ️Key Naming

Keys can be bare (key = "value"), quoted ("key-with-dashes" = "value"), or dotted (a.b.c = "value"). Dotted keys create nested tables inline.

  • No null type - TOML has no null. Omit the key or use an empty string.
  • Tables must be defined before use - You can't add keys to a table after defining a subtable.
  • Case-sensitive - Key and key are different keys.
  • Dates are strict - Must be valid ISO 8601 dates. No 2024-1-5, must be 2024-01-05.
  • No trailing commas in inline tables - {a = 1,} is invalid.

TOML vs Alternatives

TOMLYAMLJSONINI
ReadabilityExcellentGoodVerboseGood
TypesRichRichBasicNone
Comments##None; or #
NestingLimitedUnlimitedUnlimitedFlat
GotchasFewManySomeMany
Best forConfig filesComplex configData exchangeSimple config

Real-World Example: Cargo.toml

toml
[package]
name = "my-app"
version = "0.1.0"
edition = "2021"
authors = ["Developer <dev@example.com>"]
description = "A sample Rust application"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }

[dev-dependencies]
criterion = "0.5"

[[bin]]
name = "my-app"
path = "src/main.rs"

[profile.release]
opt-level = 3
lto = true

In Code

javascript
// Node.js with @iarna/toml
const TOML = require('@iarna/toml');

// Parse TOML string
const config = TOML.parse(`
[server]
host = "localhost"
port = 8080
`);

// Convert to TOML string
const tomlString = TOML.stringify({
  server: { host: 'localhost', port: 8080 }
});
python
# Python with tomllib (built-in 3.11+)
import tomllib

with open('config.toml', 'rb') as f:
    config = tomllib.load(f)

# For writing, use tomli-w
import tomli_w

with open('config.toml', 'wb') as f:
    tomli_w.dump(config, f)

Try It

Convert TOML to JSON

"TOML: Because Tom wanted a config format that wouldn't make him question his life choices at 3 AM."