<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Brandt</title>
    <description>The latest articles on DEV Community by David Brandt (@dbra90).</description>
    <link>https://dev.to/dbra90</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4084834%2Fdf51011a-eb27-493a-a201-d068cec34e9c.jpg</url>
      <title>DEV Community: David Brandt</title>
      <link>https://dev.to/dbra90</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dbra90"/>
    <language>en</language>
    <item>
      <title>Why we compile business apps from a spec instead of generating code</title>
      <dc:creator>David Brandt</dc:creator>
      <pubDate>Wed, 19 Aug 2026 10:48:22 +0000</pubDate>
      <link>https://dev.to/dbra90/why-we-compile-business-apps-from-a-spec-instead-of-generating-code-4bh3</link>
      <guid>https://dev.to/dbra90/why-we-compile-business-apps-from-a-spec-instead-of-generating-code-4bh3</guid>
      <description>&lt;p&gt;Building &lt;a href="//chromoly.io/deterministic-ai"&gt;Chromoly&lt;/a&gt; with a small team. Internal tools and AI automations, early access in January. This is the architecture argument behind it, including the part where it's a ceiling.&lt;/p&gt;

&lt;p&gt;Someone on Reddit recently told me the core claim of my product is impossible. "Not hard, not virtually impossible, but actually impossible."&lt;/p&gt;

&lt;p&gt;He didn't say why. So let me make his case for him, because the strongest version of it is real and it's the interesting part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The impossible claim:&lt;/strong&gt;&lt;br&gt;
Before any change applies to your system, we show you everything it touches, every field, workflow, and permission affected, marked safe, affected, or breaking.&lt;/p&gt;

&lt;p&gt;For code, the objection holds. Rice's theorem: no algorithm can decide non-trivial semantic properties of arbitrary programs. Any tool promising complete impact analysis over a general-purpose codebase is approximating and hoping. This isn't an engineering gap that better models close. It's math.&lt;/p&gt;

&lt;p&gt;Which is why every AI code generator has the same failure mode, and why their communities all sound identical. Ask any of them to change one component and it can touch five files you didn't mention. Not because the model is weak but because the system it's editing has no queryable structure. The AI re-derives what it thinks your app is, every time, from code plus chat history. The most upvoted complaints about AI builders right now aren't "it can't build things." They're "it won't stop changing things I didn't ask about."&lt;/p&gt;

&lt;p&gt;The trick is refusing to play. Impact analysis is impossible for arbitrary code. So: no arbitrary code.&lt;/p&gt;

&lt;p&gt;A Chromoly system is defined entirely in a closed, declarative spec - entities, fields, workflows, permissions, integrations, with every reference explicitly declared. No eval, no user-supplied code, no dynamic dispatch. The app is compiled determanistically from the spec: same spec in, same system out.&lt;/p&gt;

&lt;p&gt;Over a closed structure, "what does this change affect?" stops being undecidable and becomes boring, a graph traversal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You already trust this trick daily:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A spreadsheet knows exactly which cells recompute when you edit B4. Not because Excel solved the halting problem - because formulas are a closed language with explicit references.&lt;br&gt;
terraform plan tells you precisely what a change will create, modify, or destroy before you apply it. Same reason: declarative, closed, explicit. Nobody calls those features impossible. They work because the language was constrained until the question became answerable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A sketch of the shape:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;entities:&lt;br&gt;
  client:&lt;br&gt;
    fields: [name, email, status]&lt;br&gt;
  invoice:&lt;br&gt;
    fields: [client_ref, amount, due_date, approved]&lt;br&gt;
    refs:&lt;br&gt;
      client_ref: client&lt;/p&gt;

&lt;p&gt;workflows:&lt;br&gt;
  approval:&lt;br&gt;
    trigger: invoice.created&lt;br&gt;
    when: invoice.amount &amp;gt; 10000&lt;br&gt;
    then: request_approval(role: founder)&lt;br&gt;
Rename client.status and the compiler doesn't guess what breaks. It walks the graph: which workflows read it, which views filter on it, which permissions gate it. The answer is complete because the spec is the only place anything can live.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the AI fits and where it can't hurt you:&lt;/strong&gt;&lt;br&gt;
The AI's job is translating plain language into spec, and spec changes. It never writes freeform logic for a runtime to interpret.&lt;/p&gt;

&lt;p&gt;This kills the failure mode people assume we have: "you're praying the compiler agrees with what the AI wrote last week." Drift needs two sources of truth — what the AI meant, and what the system runs. Here there's one artifact. An invalid spec is rejected at write time, not discovered in production. When the AI is wrong, you get a rejected edit or a diff you decline. Loud failure, not silent corruption.&lt;/p&gt;

&lt;p&gt;It also answers the context-window problem without needing bigger context windows. A real system as code is millions of tokens; no model holds it honestly. The same system as a spec is thousands. In chat-based builders, the only place your app's structure exists is the chat history and the chat history runs out. A spec doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The honest part: it's a ceiling&lt;/strong&gt;&lt;br&gt;
Determinism buys all of the above, and it costs expressiveness. There is logic the schema cannot hold - custom algorithms, novel computations, anything that needs code someone would have to invent. When you ask for that, the system refuses rather than improvising.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;We think refusal is the right failure mode for business software: *&lt;/em&gt;"the system said no" beats "the AI guessed" when the system runs your invoicing. But it is absolutely a ceiling. If you need arbitrary computation, or you want code you own and hack on, a code generator plus Cursor is the better tool. We build internal tools and AI automations only - CRMs, portals, approval flows, the systems a business runs on because that's the domain where a constrained schema covers what people actually ask for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bet&lt;/strong&gt;: for internal business systems, a closed spec is expressive enough for real needs, and the things it buys like complete impact analysis, deterministic rebuilds, structure that can't be forgotten are worth more than the breadth it costs. If that bet is wrong, the product is wrong.&lt;/p&gt;

&lt;p&gt;One consequence worth noticing: when the schema can't express something users genuinely need, the fix is a new primitive in the language which every existing system immediately gets, safely, because it compiles like everything else. The ceiling rises deliberately. It never rises by accident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the constraint actually buys: maintenance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Safe changes are half the point. The other half: every system we generate compiles into one shared runtime so a Postgres patch, a model migration, or an integration fix lands once, fleet-wide. Monitoring and failure alerting live in the runtime itself.&lt;/p&gt;

&lt;p&gt;That promise is impossible over freeform generated code: every app is a unique codebase, so maintenance scales with customers until it eats you. That's why code generators hand you the code and wish you luck. One compiler and one runtime across thousands of systems is just software; a thousand bespoke codebases is a consultancy.&lt;/p&gt;

&lt;p&gt;The full chain: closed spec → decidable impact analysis → safe changes → one runtime → maintenance as a platform property, not a service promise. Remove the first link and the rest fall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why nobody else does this&lt;/strong&gt;&lt;br&gt;
Not because it's secret. Because it's a different bet than the one the market rewards in demos.&lt;/p&gt;

&lt;p&gt;Freeform generation demos better. It can attempt anything on stage. A compiler can only build what its language expresses, and it will tell you no in front of an audience. Every incumbent chose the demo. Their users chose them for "it's your code, build anything" which means restructuring around a closed spec would mean abandoning the promise their customers bought.&lt;/p&gt;

&lt;p&gt;So the constraint isn't our limitation. It's the product. Everyone else picked wide. We picked maintained.&lt;/p&gt;

&lt;p&gt;Early access opens January. Happy to argue about any of this in the comments - the Reddit thread that prompted it made the product better, and I'd rather collect the counterarguments now than after launch.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nocode</category>
      <category>architecture</category>
      <category>softwaredesign</category>
    </item>
  </channel>
</rss>
