Why Admiral is built this way
Admiral is built around a different model of how an environment changes, infrastructure and workloads alike. These are the three architectural decisions that fall out of it.
The model comes down to three claims. A change should be reviewed as the whole set of effects it has, across infrastructure and workloads, and released by an explicit decision. What an environment should be running belongs in a system that models it, not in the contents of a branch. And execution should happen inside the boundary that owns the resources being changed. Each section below takes one of those, says how conventional tooling does it differently, what Admiral does instead, and what the choice costs you.
One change should be one review
A changeset holds every component a change touches, infrastructure and workloads together, and that whole set is what gets planned, approved, and promoted.
Today those halves are reviewed apart. The Terraform change goes through one pull request and the chart bump through another, often in separate repositories on separate schedules, even though they are one change - the database has to exist before the release that reads from it means anything. Each review is sound on its own, and nobody reviews the thing that is actually happening.
The gap between them is where the interesting failures live. The reviewer of the module change cannot see which releases consume its outputs, and the reviewer of the chart bump cannot see whether the infrastructure it now expects has been provisioned. Both approvals can be correct and the environment can still end up in a state neither reviewer signed off on.
Admiral makes that set the unit. A changeset is every component the change touches, scoped to one environment; you stage it, Admiral plans it, and it waits at a single approval gate until someone releases it. There is no edit-this-component call to find in the API, because there is none to write. And because the reviewed thing is a modeled set of changes rather than a pile of file diffs, it promotes: the same set copies into the next environment as a new changeset, rebased on that environment's own deployed state and reviewed against it.
This does not make an apply atomic. A changeset is a planning artifact and an authorization boundary, not a transaction, so if a component fails partway through a dependency chain the components already applied stay applied, dependents of the failure are blocked, and the run ends as partially failed rather than unwinding itself. Recovering means another changeset to fix forward or revert. It also does not take your cloud console away: anyone with account admin can still change things out from under Admiral, and Admiral surfaces that as drift rather than preventing it. What Admiral owns is the path through Admiral.
We already have approvals in our pipeline.
You probably do, and they probably work. The question is what they are approving. Two approvals on two file diffs in two repositories is not the same as one approval on the set of effects, and tightening either pipeline does not close the gap between them, because that gap comes from reviewing the halves separately rather than from how strict each review is.
Source control and operational state are different abstractions
Git versions the source your components are built from. Admiral holds what each environment should currently be running. Collapsing the two is what leaves a file diff standing in for a set of effects.
A commit records that someone edited a file. It does not record that anyone decided an environment should change. The two get conflated because a reconciler happens to watch the branch, and once it does, that branch is the operational state whether or not anyone designed it that way.
Two things follow. The reviewable unit becomes a file diff rather than a set of effects, so you approve a YAML change and work out the consequences in your head. And the deploy trigger becomes a version bump - a commit invented for no reason except to make the watcher notice.
Admiral keeps them separate. Desired state lives in a control plane that models components and the dependencies between them, so the changeset is the reviewable unit, the plan is the diff, and applying is an act rather than a side effect of a merge. Git goes on doing what it is genuinely good at, which is versioning the module and chart source your components point at.
You give up the property that one repository checkout contains the whole picture. What an environment should be running is answerable from Admiral rather than from a directory you already have open, which puts another system in the path of that answer and a real dependency on its API and its history.
Does that not trade away the audit trail?
A commit log records that a line changed and who pushed it. Admiral records what was planned, what was approved, and an immutable revision per component capturing exactly what deployed and the values it rendered against. That is a more direct account of what happened to production, and it is the account you actually want while reconstructing an incident.
Execution belongs inside the boundary that owns the resources
Admiral never executes anything. An agent does, inside your own account or cluster, with an identity you issued - so the agent’s identity is the trust boundary rather than a setting inside Admiral.
Centralize execution and the executor’s identity has to be the union of everything it might ever be asked to do. Run one Terraform automation for several teams and it needs permission for all of their resources at once, because there is one process and it has to be able to do all of it. The workload half goes the same way: one cluster-wide reconciler serving every team ends up able to write to every namespace it serves. Isolating per team usually means splitting repositories, which is a larger change than most teams take on, so the union stays and grows.
An agent - a pull-based worker process you run in your own cloud or cluster - does the work, using whatever identity you gave it where you installed it: a cloud role for Terraform work, an in-cluster service account for workloads. Admiral holds no standing credentials to your accounts or clusters and needs no inbound path to them, so "what can this reach" is answered by the identity you issued rather than by configuration inside Admiral. Draw an agent per team, per account, or per sensitivity boundary, and a component reaches exactly as far as the agent it targets.
Scoping is per agent rather than per component, so the boundaries you get are the ones you drew at install time. Narrower boundaries mean more agents to install, monitor, and keep running. You are trading one privileged executor that is straightforward to operate for several unprivileged ones that are not.
Our cloud credentials are already centralized in CI.
Then the identity question has moved to your CI provider, and the union usually moves with it: one pipeline identity able to assume every role any job might need. What matters is not where the credentials live but whether the thing holding them is shared across teams. If your CI already issues a distinct, narrowly scoped identity per job, you have solved the same problem another way.
Read the model, not the pitch
If these tradeoffs sound unusual, that is intentional. Admiral is not a better-configured version of the tools above. It is a different model of how an environment changes, and the feature list is downstream of that. For what this looks like on a single change, see deploying Terraform and Helm together.
The docs carry these same three arguments with the mechanics attached: the run state machine, how a plan defers work it cannot yet resolve, and how a partial failure surfaces and gets recovered. Read the model before evaluating the product.