Configuration files often begin as a convenience and gradually become a source of complexity. A project starts with a few settings in JSON, then adds defaults, environment-specific overrides, shared definitions, and relationships between values. Eventually, the difficult part is no longer storing the configuration. It is understanding what the final configuration means, where each value came from, and whether two declarations contradict each other.
Aontu is an attempt to address that problem. It is an open-source language for combining structured data, schemas, and defaults into a consistent result. Its central idea is unification: rather than silently choosing one value when declarations conflict, Aontu attempts to reconcile them and reports contradictions.
I encountered Aontu through a Voxgig SDK generation project, where the generator's model describes project-level settings and generation decisions. That context made its purpose easier to understand. However, it also raised a practical question: does the additional structure make configuration easier to maintain, or does it introduce a new abstraction that developers must learn before they can get work done?
The problem with configuration by accumulation
JSON is an excellent interchange format. It is widely supported, easy to parse, and familiar to developers. But ordinary JSON does not define what should happen when multiple sources describe the same configuration differently.
Imagine that a shared configuration defines a service timeout, while an environment-specific file defines it again. A conventional merging tool might replace one value with another. That can be useful, but it can also hide an accidental conflict.
Aontu takes a different approach. Its JSON-like syntax supports references, constraints, and combinations of declarations. The goal is to make the relationship between pieces of data explicit.
For example, a simple Aontu document can define a value and refer to it elsewhere:
subtotal: 19
tax: 2
total: $.subtotal + $.tax
The reference $.subtotal points to another value in the document. The result is a model in which the total follows from the inputs instead of being maintained as a separate, potentially inconsistent number.
This is a small example, but it illustrates a useful principle: if a value can be derived, expressing the relationship directly can be safer than duplicating the result.
Unification is the interesting part
The more important feature is not the shorter syntax. It is how Aontu combines declarations.
In ordinary configuration workflows, an override is often intentional. A production environment may need a different setting from development. However, not every disagreement should be treated as an override. Sometimes two files express incompatible assumptions, and choosing one silently merely conceals the problem.
Aontu's model is designed to make those contradictions visible. Its approach is inspired by CUE, a configuration and constraint language with a similar emphasis on unification.
This distinction matters in code-generation systems. A generator may obtain API entities and operations from an OpenAPI definition while keeping package names, target languages, versions, and project-specific choices in its own model. If these declarations are combined through predictable rules, the project becomes easier to customise without modifying generated files directly.
Voxgig describes this approach in its SDK customisation documentation. The model acts as a durable place for project decisions, while generated output can be regenerated from the combined specification.
That separation is valuable. Manual changes to generated source files are often lost during regeneration; keeping intentional changes in a model or template is a more sustainable design.
A concrete validation example
Aontu is not limited to deriving values. Its tooling also supports schema validation.
Consider a configuration that requires a service to have a string name and a numeric port. A simplified model could look like this:
Service: {
name: string
port: int
}
The intent is to describe the shape of a valid service rather than merely provide one example of a service.
Aontu's command-line interface provides a vet command for checking data against a model. For example:
aontu vet service.aon config.json
The benefit is straightforward: invalid configuration can be rejected before it reaches the application that consumes it.
That said, this is where I would want to test the tooling carefully before adopting it across a team. Validation is only useful if developers understand the resulting diagnostics, know which file introduced the problem, and can distinguish a genuine conflict from an incomplete model under construction. A language that catches more errors but makes them difficult to diagnose can simply move complexity from runtime to development time.
The developer experience is part of the design
Aontu offers more than a parser. Its project includes command-line tools, editor integration through the Language Server Protocol, formatting, querying, and utilities for examining models and their evolution. The TypeScript implementation and Go implementation are also checked against a shared language-agnostic test specification.
Those are meaningful engineering choices. A shared test suite helps reduce the risk that the same model behaves differently depending on which implementation evaluates it. The command-line tooling also makes it possible to experiment without immediately embedding the language into an application.
However, there is an adoption cost.
Developers already know JSON, YAML, and the configuration conventions of their existing frameworks. Introducing Aontu means learning its reference syntax, constraint semantics, error messages, and tooling. That cost may be justified for a large model with many interacting declarations, but it is harder to justify for a handful of static settings.
Editor support deserves particular attention. Aontu documents how to connect its language server to editors, including VS Code and Neovim. But documentation for configuring an editor is not the same as a seamless, officially supported out-of-the-box experience. Teams should check the current integration options and installation requirements before making Aontu part of their everyday workflow.
I would also avoid assuming that every Aontu value will behave identically when moved into ordinary JSON. The project's documentation explicitly discusses issues such as preserving exact decimal values across JSON boundaries. This is a useful reminder that a modelling language can enforce stronger semantics internally than the data formats surrounding it can preserve.
What I would question before adopting it
My biggest concern is not that Aontu is too powerful. It is that its benefits are workload-dependent.
For a small application, a conventional configuration file plus a schema validator may be enough. The simpler solution is easier to explain, easier to integrate, and less likely to require specialised knowledge from every contributor.
For a code generator, infrastructure model, or configuration system assembled from multiple sources, the calculation changes. Relationships between values, reusable constraints, explicit conflicts, and repeatable generation can justify a more expressive language.
I would evaluate Aontu against three practical questions:
- Does it eliminate real bugs? Identify cases where conflicting declarations or invalid configuration have caused failures, and verify that Aontu catches them.
- Can the team diagnose problems quickly? Test realistic conflicts and incomplete documents, not just successful examples.
- Does it fit the existing toolchain? Check editor support, CI integration, installation, version management, and the impact on contributors who do not work on the model every day.
These questions matter more than whether the syntax looks elegant in a tutorial.
Verdict: useful for complexity, not a universal replacement
Aontu is an interesting approach to a real problem: configuration becomes difficult when several sources of truth must be combined without losing consistency. Its emphasis on unification, constraints, and explicit conflicts gives it a clear purpose beyond being another format for storing key-value pairs.
My experience encountering it in an SDK generation workflow made the separation between project decisions and generated output particularly compelling. That separation can make regeneration safer and customisation more maintainable.
But I would not recommend adopting Aontu simply because a project has configuration files. Its strongest case is a system where models are composed from multiple sources, relationships between values matter, and silent overrides are a genuine risk. In simpler projects, the additional language and tooling may cost more than they save.
The best way to assess Aontu is to take a configuration that is already causing problems, model those problems explicitly, and see whether the resulting workflow becomes easier to reason about. If it does, Aontu has earned its place in the toolchain. If not, a simpler solution is probably the better engineering decision.
Top comments (0)