intermediateDSL

A team wants to replace a configuration file format with a small language of their own. Talk them through it.

Whether the candidate prices the whole thing rather than the parser. Everyone can write a parser in a weekend; the discriminator is whether they know what the second year costs.

What a strong answer covers

  • The first question is what the current format cannot express, and whether the answer is "abstraction" — repetition that wants a loop, values that want to be computed, environments that want to differ by one field. If the pain is really schema validation or bad error messages, a schema and better diagnostics on the existing format solve it for a fraction of the cost.
  • The second question is internal or external. An internal DSL — a builder API, a set of functions in the host language — inherits the host's parser, type checker, editor support, debugger, package manager and hiring pool for free. An external DSL gives full control over syntax and, crucially, over what is *not* expressible, which is exactly why configuration languages want to be external: you can guarantee termination and absence of I/O in a way a host language cannot.
  • Then the real bill. The parser is the cheap part. What is expensive is: error messages good enough that a non-author can fix their own config; an editor mode with completion and go-to-definition, or people will not use it; a formatter, or the reviews become about whitespace; versioning and migration, because configs live in repositories for years; a testing story; and documentation. Every one of those is a thing the team now maintains instead of shipping product, and the tooling bill recurs while the parser cost is once.
  • The strongest argument for building one is the one about restriction rather than expressiveness — a language in which a dangerous thing cannot be written at all is worth more than a library that documents not to. The strongest argument against is that most configuration languages grow into general-purpose ones badly, one feature at a time, until they have conditionals, functions and a module system that nobody designed.
✓ Green flags
  • Asks what the existing format cannot express before proposing anything.
  • Distinguishes internal from external and names what each inherits or gives up.
  • Prices the tooling — editor, formatter, errors, migration — and calls it the recurring cost.
  • Uses restriction as a positive design goal, with a concrete example.
  • Names the growth failure mode and proposes a way to bound it.
✗ Red flags
  • "A parser is a weekend project, so it is cheap." The parser is the cheap part; the answer stops exactly where the cost starts.
  • "We will just embed a real language so we get everything for free." You also get file access, network access, non-termination and arbitrary imports in your configuration, which is how a config file becomes a supply-chain surface.
  • "Users will learn it, it is simple." Every user is learning it under deadline pressure while debugging something else, which is when error message quality is the entire user experience.
  • "We can add types later." Retrofitting a type system onto a deployed configuration language means breaking every existing file or accepting permanent gradual typing.

Follow-up

They have decided to build it. What is the first thing you make sure is in the design, before any syntax is chosen?

Implementation challenge

What to ask them to write or trace on a whiteboard.

Sketch the smallest language that solves their stated problem, and then list what you would refuse to add in the first year and why.

The lessons behind it