← Articles
Lukman Nuriakhmetov2026-03-315 min read

The unit of architecture

The thing we compile has kept climbing — instructions, functions, services. The next rung is the system itself.


There is a quiet pattern in how software has progressed, and it is easy to miss because it happened slowly. The unit we compile keeps climbing. We started by hand-writing machine instructions, then let assemblers produce them. We wrote functions and let compilers turn them into binaries. We described services and let build tools turn them into images we could ship. Each climb followed the same bargain: stop hand-producing the layer below, and trust a tool to produce it the same way every time.

The bargain has always paid off, and it has always felt slightly uncomfortable at the moment it was struck. Giving up control of a layer you used to write by hand is unnerving until the determinism earns your trust. Then you forget you ever did it by hand at all. Nobody hand-assembles binaries to feel in control anymore.

That climb has now stalled at the layer that matters most. The thing we most want to treat as a single, checkable object is the system itself — its services, the modules they share, the contracts between them, who owns what. And that is the one layer almost nobody compiles. We assemble it by hand on every new project, or improvise it in a chat window, and then let it live in a diagram that is wrong by the end of the week.

The thing that's missing

AI did not create this gap, but it made the edges sharp. A model will write you a service in seconds. It writes the next one from a slightly different reading of the same intent, because that is what models do. Each piece looks correct in isolation. Whether they add up to a system that holds together is left to chance and to whoever reviews the pull request, and reviewers are not graph solvers.

What's missing is a representation of the system a machine can check — not a picture, a structure. When the architecture lives only in a context window or someone's memory, every change is a renegotiation. Ports drift. Two services quietly disagree about a contract. A module gets wired in twice and nobody notices until staging falls over. None of these are hard problems individually. They are invisible because nothing is holding the whole shape at once.

A compiler holds the whole shape. That is the move Rhodd makes: it treats the system definition the way a compiler treats source. It validates the definition, builds a model, resolves the dependency graph and proves it acyclic, plans every file it will write, emits the result, and freezes what it produced. The architecture stops being an assumption and becomes an input.

What a compiler keeps that a copy throws away

A scaffold gives you a starting point and forgets it the instant it finishes writing. Everything it computed to lay those files down — the structure, the dependencies, the decisions — evaporates. That discarded part has a name worth keeping: the compiled system, the model and graph and plan a one-shot generator builds internally and then deletes.

Rhodd keeps all of it, as files you can read.

json
// .rhodd/graph.json — the system as data, not a drawing
{
  "nodes": ["web", "api", "postgres", "redis"],
  "edges": [
    { "from": "web", "to": "api", "kind": "depends_on" },
    { "from": "api", "to": "postgres", "kind": "owns" },
    { "from": "api", "to": "redis", "kind": "owns" }
  ],
  "cycles": 0
}

It keeps the model: a typed view of every service, its kind and runtime, and the modules it touches. It keeps that graph, resolved and proven acyclic. It keeps the plan — the full set of writes computed as a dry run before anything lands on disk, so you can see what a regeneration will do before it does it. It keeps ownership records that draw a hard line between the paths Rhodd generates and the source you write, so regeneration never overwrites your work. And it keeps a lock that hashes the input and the output, so the same definition produces a byte-identical result.

None of this is glamorous. It is the difference between a system you can change with confidence and one you change by archaeology.

A floor, not a driver

It would be easy to read this as a position against AI, and it isn't. Rhodd does not compete with the model writing your handler logic. It gives that work a floor to stand on. The compiler writes a handoff into .rhodd/ai that states the system's shape in a fixed reading order — context, model, graph, plan, ownership, manifest, quality — so an agent works from compiled facts instead of its best guess about them.

That matters more, not less, as more of the code is written by something with no memory of yesterday. A model's output is only as safe as the state it can see. Rhodd's job is to make that state explicit, deterministic, and identical on every run. Rhodd works without AI. AI is simply safer when the ground underneath it doesn't move.

Where this leaves us

Every climb up the ladder of compilation has been the same trade: give up writing a layer by hand, get back confidence that the layer is correct and consistent. Treating the system as the unit is that trade again, made at the rung that has resisted it longest, and made now because the alternative — a thousand individually plausible pieces that may or may not form a coherent whole — is exactly what fast code generation produces by default.

The architecture stops being the thing everyone assumes and no one can point to. It becomes a file you can read, a graph you can check, and a lock you can re-run. That is not a tool that writes your system for you. It is a tool that keeps your system after it's written — which, the longer a project lives, turns out to be the harder and more useful half.


Docs · How it works · Join the beta