Skip to content

Drift

Drift is a difference between what the code says and what really exists in the cloud. It usually means someone changed something outside a merge request: in the Google Cloud console, under a time-boxed grant, or by a command run by hand. Airframe does not try to prevent every such change; it makes sure none goes unnoticed, by checking every root every day and opening an issue when the two disagree.

The whole platform rests on one promise: what is in the code on main is what runs. Reviews, the policy pack and the audit trail all look at the code. A change made by hand skips all three, and worse, the next apply of that root may silently undo it, or fail on it, at a moment nobody expects.

Drift is not always a mistake. A maintainer fixing an outage under a grant creates drift on purpose. What matters is that it is seen and then resolved, one way or the other.

the codeon mainwhat existsin the clouda dailyscheduled planone issue perdrifting rootcodify or revert;the issue closes

Every repository with Terraform roots has a daily scheduled pipeline. In it, the tf-apply component’s drift job plans every root against the real infrastructure without applying anything. A plan that is empty means the root matches. A plan that is not empty means something drifted.

The two platform roots that deploy images, the gate’s and the architecture catalog’s, are planned against the images they last applied, which they record in their state’s images output. An image built for a commit and never deployed is therefore not drift: the plan asks whether the cloud differs from the last apply.

The three landing-zone roots that are still applied from a laptop are planned the same way, by an identity that can only read, so a change made under a grant shows up within a day.

After the drift jobs, the drift-report component turns their results into GitLab issues, as the platform’s audit identity:

  • one open issue per drifting root, labeled audit::drift, titled with the root’s name;
  • the issue lists the resources that differ and what the plan would do to each, never their values, so no secret can leak into an issue;
  • while the drift lasts, the issue is rewritten by each daily run;
  • the first run that finds the root matching again closes it.

For example, control-plane’s Drift: gate was a false drift. Every control-plane merge built a new gate image while the gate deployed only when its own code changed, and the daily plan compared against the newest build, so from 2026-09-29 most mornings reported it. The fix of 2026-10-02 made the plan compare against the images the root last applied, and the run of 2026-10-03 found the root matching and closed the issue.

Read the issue, find out who changed what and why, then choose one of two fixes:

  • Codify it. If the change was right, write it into the code in a merge request. Once it is applied, the next daily plan is empty and the issue closes.
  • Revert it. If the change was wrong, let the code win: the next apply of that root, from a pipeline on its main branch, puts the infrastructure back as the code says, and the next daily run closes the issue.

Either way, the code stays the one source of truth, and every change to it goes through a merge request and its checks.

Why the console is not the way to change things

Section titled “Why the console is not the way to change things”

The console is fine for looking. For changing, it skips everything that makes a change safe on Airframe: nobody else reviews it, no rule checks it, no plan shows what it touches, and nothing records why it was made. People’s everyday accounts cannot change production infrastructure anyway; the time-boxed grants exist for emergencies, and drift detection is what makes sure an emergency fix finds its way back into the code.

Where it lives

In the control-plane repository:

MIT license. Copyright Airframe contributors.

This site describes platform release 2026.10.20-1.