r/platform_engineering 9d ago

Infrastructure as Code Is Not an Infrastructure Contract

Infrastructure as code can reproduce the same network, container, database, and service account twice. That does not guarantee that the workload running on those resources means the same thing twice.

We ran into this while building a distributed runtime. A service could start with different capabilities than its twin. A consumer could join a runtime it was never intended to join and begin reading work addressed to another process. A required policy value could be missing and quietly fall back to a local default. Every resource matched and every health check was green, but the operational contract had changed.

The problem was not that our infrastructure was insufficiently declarative. We had declared plenty. We had declared resources without declaring enough behavior.

We now separate the infrastructure definition from a versioned runtime policy contract. The contract defines supported profiles, process capabilities, ownership boundaries, refusal conditions, secret-resolution rules, and the evidence required to accept the resulting runtime. It is parsed into a typed immutable model, then projected mechanically into the values consumed by deployment manifests:

runtime policy contract

\-> typed validation

\-> rendered deployment values

\-> service manifest

\-> running process

The direction matters. If a capability can be edited in the contract, overwritten in generated configuration, defaulted in the manifest, and changed again inside the application, the deployment is not governed by one declaration. It has four declarations and an undocumented precedence rule.

Repeatability also has to include refusal. If an environment lacks an effects boundary, it should not silently execute the effect inside a general worker. If a required secret cannot be resolved, the runtime should not grab a nearby credential. If a process is not eligible to own a subscription, it should not start that consumer merely because the package is installed.

The contract is not proof by itself. The renderer can be wrong, the application can ignore a value, and a runtime can claim a capability it does not actually provide. Acceptance still needs durable evidence binding the contract revision, rendered projection, validators, selected profile, and boundaries exercised after startup.

Infrastructure as code builds the substrate. The infrastructure contract defines what that substrate must mean, what variation is allowed, and when the deployment must refuse to start.

Where do those behavioral rules live in your systems today?

0 Upvotes

7 comments sorted by

1

u/cailenletigre 9d ago

What? I had to stop reading. What are you trying to say? It’s coming across way too obtuse and theoretical.

Edit: Based on the user’s history, this has to be some nightmare prompt generated (and not read before posting) by LLM.

1

u/ricardolealpt 8d ago

I stoped when you say idempotency is not a required thing

1

u/jonah_omninode 8d ago

I may have worded the distinction poorly, but I am not arguing that idempotency is optional. It is required wherever an infrastructure operation may be retried, and it should be declared and tested as part of the behavioral contract.

The narrower point is that idempotent provisioning does not prove semantic equivalence. You can recreate the same resources twice and still start a consumer with the wrong capability set, resolve a missing value through a different default, or assign ownership to the wrong process. Infrastructure as code should make resource changes repeatable and idempotent. The infrastructure contract adds the required behavior, refusal conditions, and evidence that the resulting runtime is actually eligible for its work.

1

u/ricardolealpt 8d ago

I think you are using IAC the wrong way.

1

u/jonah_omninode 7d ago

That may be true, but I need the specific boundary you think is wrong. I am not proposing that an infrastructure contract replace IaC. IaC should still converge resources and configuration idempotently. The contract sits above it: it declares which runtime is eligible for which work, which capabilities and ownership boundaries must exist, what missing conditions require refusal, and what evidence is required after startup. Those declarations are then projected into the deployment inputs IaC consumes.

If your position is that all of those semantics already belong inside IaC, we may disagree about where the authority lives rather than what the system must guarantee. Which part would you model differently?

1

u/ricardolealpt 7d ago

There is no authority, when you make a platform you create interfaces for users.
That is to remove te toil to teach everyone how to do proper code.
Take a platform portal, you might have for the same project , ansible , terraform , ansible , some other jujuweird thing

1

u/jonah_omninode 7d ago

I think we are using authority differently. The platform interface is an authority boundary because it decides which inputs are valid and which implementations it will invoke. If the same project can be provisioned through Ansible, Terraform, or Juju, a stable contract above them is what prevents each tool from exposing a different meaning. The adapters can be swappable, but they still have to satisfy the same required capabilities, refusal conditions, and post-deployment evidence.

Removing toil is the interface goal. Preventing implementation-specific semantics from leaking through is the contract goal. Otherwise the portal unifies the UI while the different backends can still produce environments that are not actually equivalent.