If you write code, manage servers, tweak game settings, or maintain toolchains, you almost certainly cannot avoid config files.
A lot of the time, what really blows up a program is not the algorithm or the framework, but one tiny line of configuration: one missing space, one extra comma, or one value written in a way the system did not expect. Looking at common config formats side by side naturally brings us back to a few core questions:
- Which formats are friendlier for humans to write?
- Which formats are friendlier for machines to parse?
- In the AI Agent era, will the role of config files start to change?
This article is a concise attempt to organize that question.
01 A config file is basically a negotiation between humans and machines
There is one way to put it that I think is especially accurate: a config file is really a kind of behavioral contract between humans and programs.
Its value is obvious. You do not need to rewrite business logic or recompile anything. By changing just a few lines of text, you can alter website behavior, application logic, deployment behavior, or even game graphics and hidden options.
The problem is that this contract contains a built-in tension.
From the human side, what we want is:
- something readable, writable, and structurally clear
- preferably with comments so we and others can understand it later
- as little repetition as possible, ideally with reuse and modularity
- and a format that does not instantly explode because of one small mistake
But from the machine side, elegance is irrelevant. It mainly cares about two things:
- parsing must be fast
- the rules must be strict, types must be clear, and ambiguity should be minimized
That is why config formats are always pulled between “human-friendly” and “machine-friendly.” The better a format is for human reading, the more work machines often need to parse it. The more efficient it is for machines, the easier it often is for humans to make mistakes while editing it.
02 INI: simple and direct, but limited
Let’s start with INI.
Its strengths are extremely straightforward:
- simple structure
- sections plus key-value pairs that are easy to understand at a glance
- support for comments
- well suited for lightweight configuration, such as game tweaks or basic environment settings
If you have ever modified older game settings or manually adjusted tool parameters, you have probably seen it.
But INI also has obvious limitations. Its structure is too flat and it does not naturally represent deep nesting or arrays. On top of that, it usually lacks a strict type system, so many values are basically just strings and the program has to decide how to interpret them.
That makes INI feel like an old but convenient utility vehicle: great for light work, but easy to outgrow once the project gets more complex.
A very typical INI file might look like this:
|
|
03 XML: rigorous and stable, but tiring to write
The second major format is XML.
If you have maintained older Java projects or seen large configuration files full of paired closing tags, it should feel familiar.
The strengths of XML include:
- clear hierarchical structure
- support for comments
- strict rules
- strong validation when paired with a schema
That means machines can know field types, cardinality, and structural constraints before they even begin real parsing, which gives a strong sense of safety.
But its cost to humans is equally classic:
- verbose tags
- lots of visual noise
- files that expand quickly
- and one missing closing tag can sometimes break the whole page
That is why XML feels like a fully stamped formal contract. Machines like it, while humans often get tired maintaining it. Many newer projects no longer choose it first, but in older systems and strict-rule environments it still has not fully disappeared.
The same config written in XML might look like this:
|
|
04 JSON: dominant for data exchange, awkward for hand-edited config
In modern development, JSON is almost impossible to avoid.
The classic judgment about JSON is this: it is excellent as a data interchange format, but a little awkward as a human-maintained config format.
Its advantages include:
- clear object and array structures
- network-friendly transmission
- mature parsers
- strong fit for web APIs and frontend-backend communication
Especially next to XML, JSON looks much lighter. The same structure is often shorter in JSON, and much easier to send over networks.
But it has one major flaw: standard JSON does not support comments.
Its syntax is also strict:
- keys must be in double quotes
- the last item cannot have a trailing comma
- one missing symbol can immediately break everything
So JSON is excellent for APIs and service-to-service exchange, but not always ideal for configuration that humans need to edit, explain, and revisit often.
For example:
|
|
05 YAML: highly readable, but indentation and implicit typing can betray you
If you have worked with Docker, CI/CD, Kubernetes, or deployment automation, then you have almost certainly dealt with YAML.
Its biggest appeal is how clean it looks:
- fewer braces and quotes
- indentation expresses hierarchy
- comments are supported
- anchors can be used for reuse
So from a first-glance human perspective, YAML usually feels friendlier than JSON.
But the problem is also exactly there. It hides a lot of complexity, and in real use it often produces two classic failure modes:
- indentation hell
- implicit type conversion
Indentation issues are easy to understand: one extra or missing space can break the config. Worse still, implicit type conversion means some values that look like plain strings may be interpreted automatically as booleans or some other type.
That is why so many people praise how good YAML looks and at the same time suffer badly from it. It is genuinely good for human readability, but machines do not parse it effortlessly, and different parser libraries may even disagree in subtle ways.
The same config written in YAML usually looks cleaner:
|
|
06 TOML: a balance between readability and determinism
TOML is often presented as a modern balanced answer.
Its appeal is that it combines some of the directness of INI with some of the type clarity of JSON:
- support for comments
- clear structure
- stronger, more explicit typing
- more natural handling of common types such as date and time
- far fewer of the implicit-conversion traps common in
YAML
It has also become increasingly common in modern toolchains, such as Python’s pyproject.toml.
Of course it is not perfect. For deeply nested structures, TOML can become verbose, and path-style writing can feel repetitive. But for small to medium project config, tool config, and package-management config, its overall experience is often very steady.
If you want a format with comments, clear meaning, and low parser pain, TOML is a very strong candidate.
A common TOML example looks like this:
|
|
07 .conf and Apache config: not a universal format, but a domain language
One point that is worth emphasizing is that many people see .conf and assume it is a single standard format. It is not.
.conf is just a filename suffix for “configuration.” What the contents look like depends entirely on the specific system’s own rules. In other words, .conf is more like a broad category than a standard syntax.
Take Apache config as an example. Its style is very representative:
- part of it looks like single-line directives
- part of it looks like tagged blocks with scoped behavior
- and it fits very naturally in the domain of web servers
Its strengths are practical for operations work, especially when expressing permissions, routing, and virtual hosts. The downside is that it serves its own ecosystem and does not have much general-purpose portability.
That makes it closer to a domain-specific language: great in the system it was designed for, but not something to treat as a universal config format.
For example, a minimal Apache-style config looks more like a directive list:
|
|
08 Protocol Buffers: industrial-strength typing, but with a higher barrier
Protocol Buffers are not really “just write a config file by hand” anymore. They are closer to a formal data definition and serialization system.
Their strengths are substantial:
- strong typing
- explicit schema
- good forward and backward compatibility
- compact binary transmission
- efficient machine processing
But the costs are equally clear:
- you need to define
.protofiles first - you need tools and a compilation step
- and the barrier is relatively high for small projects
So they are not ideal when you just want to configure a small tool. But if you are building large systems, RPC services, distributed systems, or long-lived data protocols, they are often far more reliable than lightweight config formats.
Their style is closer to “define the structure first, then generate code”:
|
|
09 In the AI Agent era, Markdown may become a config format again
The most interesting part of this discussion is putting Markdown into the category of “config formats.”
From a traditional programming perspective, that sounds strange, because Markdown normally feels more like a documentation format. But if the target is no longer a rigid parser and instead a large language model or AI Agent, the argument actually makes sense.
Why?
Because traditional programs depend on strict syntax and fixed fields, while large models are much better at understanding meaning, structure, and context. For them:
- headings are hierarchy
- lists are steps
- bold text is emphasis
- natural language itself can carry rules
So when the target of configuration changes from “a rigid parser” to “an agent that can understand meaning,” then Markdown, as a human-friendly structured text format, may actually become a more natural kind of configuration.
That leads to a very important judgment: in the traditional software era, many config formats existed to make humans adapt to machines; in the AI era, machines are beginning to adapt to human expression instead.
For example, task configuration for an agent might simply be written like this:
|
|
10 So how should you choose?
If we compress the whole discussion, I would group the choices roughly like this:
- if you want extremely simple, lightweight, flat config:
INI - if you want strong structure, strong validation, and legacy compatibility:
XML - if you want network transmission and interface exchange:
JSON - if you want high readability plus cloud-native and deployment config:
YAML - if you want a steadier modern general-purpose config experience:
TOML - if you want domain-specific internal rules:
.conf/ Apache-style DSLs - if you want industrial protocol design and long-term evolution:
Protocol Buffers - if you want natural expression and task orchestration for AI Agents:
Markdown
So there is no single “best config file format.” It depends on who you are writing for:
- humans maintaining the system
- machines parsing at high speed
- services communicating with each other
- or AI Agents that need to understand and execute
Short conclusion
The history of config files is, at its core, the history of humans and machines constantly renegotiating where the cost of understanding should sit.
In the past, humans had to adapt to machines, so we had to memorize brackets, indentation rules, quotes, and rigid syntax. Now that large language models and agent systems are getting better at understanding natural expression, “configuration” itself is beginning to change.
Perhaps in the future, many config scenarios will no longer revolve around one fixed syntax, but around structured statements of intent. Until then, formats like JSON, YAML, TOML, INI, and XML will continue to coexist, each occupying the role that fits it best.