Your Landing Zone Is a Snapshot, Not a Standard

Last time I said we’d look at what happens when operating models drift over time, and why the platform you designed slowly becomes different from the platform you’re actually running. Drift is a big idea, and it shows up in a lot of places across a platform. So over the next few posts I want to take it apart piece by piece, starting with the one most people never think to check: the landing zone itself.

The day you deployed your Azure Landing Zone, it was current. It probably reflected Microsoft’s guidance, your policy decisions, and your networking design as they stood on that day. Every day since, it has been getting older. Not broken, not failing, just quietly falling behind the environment it was designed to govern.

Most teams treat the landing zone as a foundation. You pour it once, it sets, and you build on top of it. That mental model is exactly the problem. A landing zone is not concrete. It is a living configuration that has to keep pace with three things that never stop moving: Microsoft’s platform and guidance, your organisation, and the threat landscape you operate in.

What “current” actually means

When people talk about keeping a landing zone current, they tend to focus on its implementation. But currency is broader than whether the code still runs. It is the alignment between three things: the guidance available now, the landing zone you have implemented, and what your organisation needs today.

The first is the guidance. Microsoft maintains its Azure Landing Zone architecture and implementation options, and they move forward. New Azure services land and need governing, policy recommendations get added or deprecated, and management group patterns shift. Even if you never consume Microsoft’s modules directly, that guidance is one of the yardsticks your design gets measured against.

The second is your implementation. When we built our landing zone, we didn’t consume Microsoft’s pre-built modules wholesale. They’re good, and they’re a sensible reference, but they encode broadly applicable defaults and design choices that do not necessarily align with how your organisation operates. So we wrote our own landing zone modules. That gave us a design that worked for our operating model. It also means we own every line of it, and everything we own is something we have to keep current ourselves.

The third is the organisation the landing zone serves. Teams change, responsibilities move, new regions and services are adopted, regulatory obligations evolve, and yesterday’s exceptions become today’s undocumented baseline. A landing zone can still match the design you approved and no longer match the business it is supposed to support.

Currency is the gap between all three. And here is the part that catches people out: there is no update button. Nobody ships you a patch for a landing zone you wrote yourself. Someone has to look at what changed in the guidance, the organisation, and the tooling underneath, decide whether it applies to you, and make a call.

The tooling moves under you too

There’s a currency problem that has nothing to do with Azure guidance at all, and if you write your own modules you feel it directly: the tooling underneath your code keeps moving.

Terraform provider upgrades are the obvious example. The AzureRM provider ships regularly, and major versions introduce breaking changes. A resource argument gets renamed, a default changes, a block that was optional becomes required, or a resource type gets restructured entirely. Your landing zone code was written against the provider version that was current when you wrote it.

Provider versions need to be constrained and locked so that plans remain predictable, but that only controls when change reaches you. It does not remove the maintenance obligation. Leave the lock untouched for long enough and the eventual upgrade becomes a project. Update it casually and an ordinary dependency change can alter or break a plan. The answer is a deliberate upgrade cadence: planned, tested, and reviewed like any other production change.

The same logic applies to Terraform itself, to any modules you pull in, and to the state that ties it all together. None of it is static. All of it is a maintenance surface you took on the moment you decided to build for your organisation rather than accept the defaults. That may have been the right call. It just isn’t a free one.

Where the drift actually happens

Changes in guidance and tooling are the more visible kind of drift. There’s a changelog to read, a release note to check, a provider version number that tells you you’re behind. The dangerous drift is the quiet kind, the kind nobody wrote down and no version number will flag.

Policy drift. This is the big one. Your policies were set to match a point-in-time view of what your organisation cared about. Since then, new Azure resource types have arrived that your governance layer has never assessed. Broad controls may still apply, but service-specific risks and configuration requirements remain uncovered. Not because a policy failed, but because no policy was ever written for something the original design did not anticipate.

Exemption drift. Every exemption you granted was a decision made in a context. “Allow this resource type in this subscription for this project until the end of the quarter.” The quarter ended. The project shipped. The exemption is still there. Multiply that across a couple of years and your carefully designed policy baseline has more holes in it than anyone can account for, and nobody can tell you why half of them exist.

Networking drift. The hub was designed for the estate you had. Then you added regions and spokes, and ran out of address space in a range someone sized for half the workloads you now run. Temporary routes became permanent, connectivity was added outside the original design, and the topology in the diagram stopped matching the topology in Azure a long time ago.

Security drift. The threat landscape moved, but your baseline did not. Diagnostic settings still reflect the services you used two years ago. New resource types send no useful logs to the security team. Controls that once represented a reasonable minimum are still present and still passing, even though the minimum itself has changed. Compliance with an old baseline can look reassuring right up until somebody asks whether it still protects anything.

Ownership drift. This is where it ties back to the last two posts. Even if the landing zone configuration is perfect, if nobody owns keeping it current, it will fall behind by default. Currency is not a property of the configuration. It is a property of the operating model. Somebody has to be answerable for the question “is our landing zone still fit for what we run today?” In a lot of organisations, nobody is.

Why this gets ignored

Landing zone currency is the easiest thing in the world to defer, and for a reason that makes complete sense in the moment. Nothing breaks.

An expired certificate takes a service down. A failed patch shows up in an alert. Landing zone drift does none of that. The platform keeps running. Workloads keep deploying. The gap between designed and operated widens silently, and it costs you nothing until the day it costs you a great deal. Usually that day is an audit, a security incident, or a migration that assumes a baseline that no longer exists.

This is the through-line of the whole series. Day 0 problems announce themselves. Day 1 problems accumulate in silence and present the bill later. The landing zone is the purest example of it, because it is the layer everything else sits on, and it is the layer nobody is watching.

Treating the landing zone like production

The fix is not a tool. It is a decision, and it is one I touched on right back in the landing zone design post: treat your landing zone like production, because it is.

That means a few concrete things.

Your landing zone lives in code, and that code is under the same review, testing, and pipeline discipline as anything else you’d call production. If your landing zone was clickops’d into existence, or if it was deployed from IaC once and then edited in the portal, you no longer have a reliable source of truth. What is deployed in Azure has to remain reproducible from the configuration in the repo, and portal changes have to be reconciled rather than quietly accepted. This is the drift I wrote about in the Terraform drift post, applied to the most important configuration you own.

It means somebody reviews what changed upstream, on a cadence, and decides what applies. Not just the Azure guidance, but the tooling too. Provider upgrades get planned and tested like any other change, not deferred until the version gap turns a routine bump into a migration. A named owner, a regular checkpoint, and a documented decision each time, even when the decision is “nothing this cycle applies to us.” That record is what stops the silent gap from opening.

It means your exemptions have expiry dates and someone actually enforces them. An exemption without an end date is a permanent hole you’ve forgotten you dug.

And it means you accept that “current” is never a finished state. You are not trying to reach currency. You are trying to operate a process that keeps the gap small enough to manage. The landing zone is never done, in exactly the same way production is never done.

The point

A landing zone gives you a strong start. It does not give you a standard that maintains itself. Without ownership and a process for keeping it current, it begins the slow slide from “the platform we designed” to “the platform we happen to be running.”

Next time I want to look at patching, which is the drift people do think about, and yet somehow it’s the one that generates the most arguments about who’s actually responsible for it.

Your subscription could not be saved. Please try again.
Your subscription to deniscooper.co.uk has been successful.

Join Cloud Engineers Who Build Smarter on Azure

Free checklists, practical guides and the latest posts — built for cloud engineers working with Azure and Terraform.

Leave a Comment