Configuration files form the backbone of modern software development, allowing developers to externalize settings and parameters without hardcoding them into applications. While YAML has become ubiquitous in this space, many developers find its whitespace-sensitive syntax and complex features overwhelming. This can lead to hard-to-debug errors and configuration drift as projects grow.
In this post, we’ll explore several alternatives to YAML that promise simpler, more maintainable configuration experiences while still providing the flexibility modern applications need.
The YAML Challenge
YAML (Yet Another Markup Language) has become the de facto standard for configuration files in many ecosystems, particularly in cloud-native and DevOps tooling. Its human-readable format and support for complex data structures made it an attractive alternative to XML and JSON.
However, YAML comes with several challenges:
- Whitespace sensitivity: Indentation errors can lead to hard-to-debug issues
- Complex type system: Implicit type conversion can cause unexpected behavior
- Too many features: YAML’s extensive specification includes features many users don’t need
- Inconsistent implementations: Different parsers may handle edge cases differently
- Security concerns: Some implementations allow code execution by default
Let’s look at some alternatives that address these challenges while maintaining or improving upon YAML’s strengths.
TOML: Simple and Explicit
TOML (Tom’s Obvious Minimal Language) was created specifically to be a more straightforward configuration language. It’s designed to be easy to read and write with unambiguous semantics.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# This is a TOML document title = "TOML Example" [owner] name = "Tom Preston-Werner" organization = "GitHub" bio = """ GitHub cofounder & CEO Likes tater tots and beer. """ [database] server = "192.168.1.1" ports = [ 8001, 8001, 8002 ] connection_max = 5000 enabled = true |
Key benefits of TOML:
- Clear, INI-like syntax with explicit tables
- No whitespace sensitivity
- Simpler type system with less ambiguity
- Excellent for configuration-specific use cases
- Better error reporting due to simpler syntax
TOML has gained significant adoption, including in Rust’s Cargo, Python’s Poetry, and the Hugo static site generator.
HCL: Configuration for Infrastructure
HashiCorp Configuration Language (HCL) was created by HashiCorp for their suite of infrastructure tools like Terraform, Vault, and Consul.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" // This is a comment tags = { Name = "ExampleInstance" Environment = "development" } } |
Key benefits of HCL:
- Designed specifically for configuration with a focus on DevOps
- Native support for functions and expressions
- Block-based structure that maps well to resources and objects
- Better readability for deeply nested structures
- Clear distinction between configuration and logic
HCL particularly shines for infrastructure-as-code scenarios where explicit structure and resource definitions are crucial.
JSON5: Making JSON More Human-Friendly
JSON5 extends standard JSON with features that make it more suitable for hand-written configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ // Comments! unquoted: 'Strings can use single quotes', "trailing-comma": "in objects and arrays", hexadecimal: 0xdecaf, infinity: Infinity, // and NaN multiline: "String can span\ multiple lines", leadingDecimal: .8675309 } |
Key benefits of JSON5:
- Fully compatible with JSON
- Supports comments
- Relaxed syntax (trailing commas, unquoted keys)
- Familiar to anyone who knows JavaScript
- Wide language support through transpilation to JSON
JSON5 is ideal when you need to enhance JSON for configuration while maintaining compatibility with existing JSON tooling.
CUE: Configuration + Unification + Evaluation
CUE is a newer, more ambitious language that focuses on data validation and generation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#Person: { name: string age: >=0 & <=120 email?: string // optional } john: #Person & { name: "John Doe" age: 37 email: "john@example.com" } |
Key benefits of CUE:
- Powerful type constraints and validation
- Schema and data in the same format
- Strong composition through unification
- Ability to generate configurations for multiple targets
- Data policy enforcement through schema inheritance
CUE excels in complex environments where validation, composition, and policy enforcement are crucial.
StrictYAML: Simplified YAML
For those who still prefer YAML’s overall approach, StrictYAML offers a more constrained version with fewer surprises:
1 2 3 4 5 6 7 8 9 10 |
# StrictYAML example name: John Smith age: 45 possessions: - car - guitar - television |
Key benefits of StrictYAML:
- Subset of YAML with removed ambiguities
- Explicit schema validation
- No implicit type conversion
- Preserves comments when modifying
- Better error messages
StrictYAML is particularly useful for Python projects that want YAML’s readability without its complexity.
Dhall: The Programmable Configuration Language
Dhall takes a different approach by providing a programmable configuration language:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-- Dhall example let Config = { name : Text , port : Natural , debug : Bool } let defaultConfig = { name = "example" , port = 8080 , debug = False } in defaultConfig // { debug = True } |
Key benefits of Dhall:
- Strong type system prevents configuration errors
- Imports and functions reduce repetition
- Non-Turing complete (guaranteed to terminate)
- Can export to YAML, JSON, and other formats
- Built-in safety features prevent remote code execution
Dhall works well for large, complex configurations where DRY principles and type safety are important.
UCL: Universal Configuration Language
UCL (Universal Configuration Language) combines elements from NGINX configuration, JSON, and YAML:
1 2 3 4 5 6 7 8 9 10 11 12 |
section "foo" { key = value; subsection { # Comment array = [value1, value2, value3]; number = 10k; // 10 kilobytes time = 15d; // 15 days } } |
Key benefits of UCL:
- Flexible syntax with multiple styles
- Macros and variables
- Built-in data type conversion (human-readable units)
- Can read UCL, JSON, and YAML
- Schema validation using JSON Schema
UCL is especially popular within the FreeBSD ecosystem and applications like Rspamd.
NEON: Nette Object Notation
NEON was created for the Nette Framework in the PHP ecosystem and shares similarities with YAML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# NEON example services: - SomeService database: driver: mysql host: localhost dbname: test user: root password: secret # Multiline strings description: ''' This is a multi-line description that preserves formatting. ''' |
Key benefits of NEON:
- Allows both tabs and spaces for indentation (unlike YAML)
- Support for multiline strings with simple triple-quote syntax
- Entity syntax for more complex structures
- Integration with PHP IDEs (especially PHPStorm via plugin)
- Used by popular PHP tools like PHPStan
NEON is particularly well-suited for PHP applications, especially those using the Nette framework or related tools.
Choosing the Right Configuration Format
When selecting a configuration format, consider these factors:
- Ecosystem compatibility: What formats are commonly used in your technology stack?
- Human vs. machine priority: Is the configuration primarily written by humans or generated?
- Complexity needs: Do you need simple key-values or complex data structures?
- Validation requirements: How important is schema validation and type safety?
- Learning curve: How easily can team members adapt to the format?
Format | Whitespace Sensitive | Comments | Schema Support | Main Strength |
---|---|---|---|---|
YAML | Yes | Yes | External | Widespread adoption |
TOML | No | Yes | External | Simplicity and readability |
HCL | No | Yes | Native | Infrastructure modeling |
JSON5 | No | Yes | External | JSON compatibility |
CUE | No | Yes | Native | Validation and generation |
StrictYAML | Yes | Yes | Native | Safer YAML subset |
Dhall | No | Yes | Native | Type safety and programmability |
UCL | No | Yes | Native | Multiple syntax styles |
NEON | No (allows both) | Yes | External | PHP ecosystem integration |
Thoughts
While YAML remains popular due to its widespread adoption, developers facing configuration complexity should consider alternatives that might better fit their specific needs. TOML offers simplicity, HCL provides infrastructure focus, JSON5 maintains JSON compatibility, NEON serves the PHP ecosystem especially well, and newer options like CUE and Dhall bring advanced features for validation and composition.
The best choice depends on your project’s specific requirements, ecosystem compatibility, and team preferences. By understanding the strengths and weaknesses of each alternative, you can make an informed decision that reduces configuration headaches and improves maintainability.
Consider starting small by adopting an alternative for a new component or microservice before committing to a full migration. And remember, configuration should be a tool that serves your project, not a source of unnecessary complexity.