Domain-specific languages your experts and your AI can both read.
A DSL captures your domain precisely enough that a domain expert can read it and a machine can check it. We design and build the whole thing: the language, the editor, the validator, and the generators that turn it into running code.
A general-purpose language can express every one of these. Your domain only needs a few of them.That is the whole idea. The language is drawn around what actually varies in your business, so what is meaningless in your domain cannot be written down in the first place—and what can be written down, a machine can check.
Benefits
A DSL narrows a domain down to what actually varies. That makes the rules explicit instead of buried in code, gives the people who own those rules a way to change them safely, and gives you a validator that mechanically rejects what is wrong.
Rules your domain experts can change
The people who own the rules edit them directly, in vocabulary they already use, instead of queuing behind a development team for every variation.
Mistakes caught by a parser, not in production
A DSL ships with a validator. Invalid input is rejected before it runs, and the error is phrased in domain terms rather than as a stack trace.
Less code to write and to own
One language plus a deterministic generator replaces the hand-written variations underneath it. Fewer lines to maintain, and they stay consistent by construction.
Where AI fits
LLMs made code cheap to produce. They did not make it cheap to trust: the generated diff still has to be understood by someone, and that review is now the bottleneck. A DSL changes the economics on both sides of that problem.
A smaller target for the model
A general-purpose language offers dozens of valid ways to express the same intent. A DSL strips that variation away, so a handful of examples of your language is enough for a model to produce correct output.
A validator that can say no
Because a DSL has a parser and a type system, generated output that breaks your domain rules is rejected mechanically—and the error is specific enough that the agent can repair it without a human in the loop.
Review intent, not diffs
Twenty lines of DSL that a domain expert can read and approve, instead of five thousand lines of implementation that nobody has time to check properly.
A cheaper model is enough
A narrow language means fewer decisions to make and far less text to emit, so the same task costs less reasoning and fewer tokens. Work that needs a frontier model against a general-purpose language often fits a smaller and cheaper one against a DSL—including models you can run on your own hardware, so the code never leaves your network.
We are not alone in this reading. Unmesh Joshi makes the same argument in DSLs Enable Reliable Use of LLMs on martinfowler.com: a DSL exposes a narrow set of domain concepts, so a few in-context examples are enough for a model to generate correct syntax, and the deterministic validator that comes with the language lets an agent check and repair its own output—with errors phrased at the level of the domain rather than as a stack trace.
The prompt is disposable. The DSL and the semantic model behind it are the asset that stays. This works as long as the language stays genuinely small and constrained—keeping it that way is the hard part, and it is the part we do.
Our approach
We start from your domain, not from a technology choice. We work with your experts to find the concepts that actually vary, design a language around them, and build what makes it usable in practice: editor support, validation, and generators that produce code you can ship. We use ANTLR, Langium, JetBrains MPS and our own open-source tooling, choosing per project rather than per habit.
What changes, in practice
A promotions engine for an online store, before and after the language exists.
This is a simplified account of real work, for an American client of ours who was defining new promotions every week.
Without the DSL
Marketers spend a fair amount of time studying the data and coming up with new promotions. One thing they have learned is that targeted promotion is the key: each kind of customer responds to different kinds of offers. Some of them just want discounts, others value free shipping a lot. So marketers devise more and more of these promotions and each time they have to run to developers to ask them to implement those.
Developers get a steady stream of small promotion requests. Each one is tedious, each one is slightly different, and every so often one of them goes wrong on the live store—which is an expensive kind of mistake. On top of that, the requirements arrive half-specified, so every promotion costs a few rounds of back and forth before it is right.
With the DSL
Marketers define promotions themselves in a small DSL, with far more control than a configuration panel would give them. They can simulate a promotion before it goes live and see what it would have paid out on real data. As the promotions get more sophisticated, the language earns its keep rather than running out of room.
Developers can now focus on more interesting tasks. At the beginning they helped marketers learn the DSL, but now that marketers are independent developers can focus on improving the platform and its performance—the work they like a great deal more than writing another promotion for diapers targeted at mothers between 20 and 30 living in Idaho.
on checkout
when
date of order is between 5/1/2026 and 5/8/2026
and country of customer is US
and total of cart is at least 45 USD
and redemptions is empty
then
[give free shipping on this order]What decides whether it survives your domain experts
Most DSLs that fail do not fail technically. They fail because the people they were built for stopped opening them. Four things decide that, and we would rather set them out now than discover them together in month five.
- An expert has to be able to read it out loud. That is the test the promotion above passes: no operator a marketer would not say in a meeting, dates written the way they already write them. If a construct needs a developer to explain it, it belongs on the generator side of the line, not in the language.
- It has to refuse things. A DSL that can express anything is a programming language with an unfamiliar syntax, and the experts go back to asking developers. The validator is what makes the language worth reading — and the error it prints has to name the rule in the domain’s own words, which is the editor’s job as much as the grammar’s.
- It has to stay small while the domain grows. Every escape hatch is requested for one urgent case and then used for everything. Refusing those requests, and moving what they were really asking for into the model instead, is the work that keeps a DSL a DSL. It does not end when the first version ships.
- It has to be maintainable without us. The grammar, the syntax tree and the tooling underneath are Starlasu and LionWeb, both open source and public, so there is no proprietary representation only we can read. Your team can keep changing the language, or another supplier can.
When we will tell you not to build one
If the rules change once a year, a configuration file is cheaper. If exactly one person understands the domain, you have a documentation problem before you have a language problem. If the variation is genuinely unbounded, a DSL will either become a general-purpose language or be abandoned. We would rather say that in the first meeting than sell a language that ends up unused.
Ready to transform the way you develop software?
Tell us about the domain you are trying to tame. We will tell you honestly whether a DSL is the right answer for it.