Why Azure Architecture Documentation Fails — and What a Documentation Workflow That Actually Works Looks Like
Most Azure architecture documentation is a record of intent, not a record of fact. This post explains why static documentation always drifts from the actual environment — and what an Azure Resource Graph-based documentation workflow looks like in practice.
Why Azure Architecture Documentation Fails — and What a Documentation Workflow That Actually Works Looks Like
TL;DR: static architecture docs drift because nothing connects them to the Azure control plane. Query Azure Resource Graph on a schedule, write the output to GitHub or Confluence, and your documentation becomes a formatted export of what’s actually running instead of a separate drawing of it.
There’s a Confluence page in your organisation that was accurate about 18 months ago. You know it’s wrong. So does everyone on the team. And every time someone starts updating it, something else has changed before they finish.
By now you’ve made a quiet peace with it. The docs are wrong. Better than nothing. New engineers get a verbal briefing on the gap between what’s written and what runs, you tell auditors the diagram is “approximately current,” and you keep meaning to fix it properly. Which means it never gets fixed.
This isn’t a discipline problem. It’s a structural one. The structure is what has to change.
Drift is structural, not sloppiness
Visio, draw.io, a Confluence page, a PowerPoint deck. None of them is wired to the Azure control plane. They capture an architect’s mental model at one moment, and Azure keeps moving after that. Nothing inside a Confluence page can notice it’s become wrong. It just sits there, quietly drifting from reality.
Take a normal month. Someone provisions a storage account for a feature release. Two NSG rules get modified during an incident. A service principal is created for a new integration and handed Contributor on a resource group. A Log Analytics workspace goes up in a second region. An old VM is decommissioned. The identity team ships three new Conditional Access policies.
None of these, on its own, is worth a documentation update. None is big enough. But add them up over six months, over twelve, and the documented architecture no longer describes the thing that runs. Nobody can tell you when the diagram stopped being accurate. It happened one change at a time.
A Terraform plan tells you the moment desired state diverges from actual. A static document just waits.
Four documents, four relationships to truth
Most Azure environments at scale carry three or four documentation layers. Knowing which one to trust for which job is half the battle.
The original architecture design, the document produced during the initial deployment project, is usually the best historical record. It describes what got built. Not what runs now.
The IaC repository (Terraform, Bicep) sits closer to intended state. But it drifts too: engineers make portal or CLI changes outside the pipeline, resources get imported into Terraform state without full configuration parity, and drift piles up between plan runs. What it records is what the pipeline last deployed.
Then the Confluence or SharePoint page. This is the one that goes to auditors. It reflects the environment as of the last major release or compliance review, plus whatever annotations someone added when they noticed a change. Lowest fidelity of the three. Highest visibility.
And Azure Resource Manager itself: the actual state, queryable through Azure Resource Graph, correct at any given moment. Most teams treat it as plumbing. It’s the only documentation that can’t be wrong.
When the diagram became a finding
A Dutch SaaS company (around 140 employees, Series B, financial services sector) went through a NIS2 readiness audit in early 2025. The auditor asked for current network topology documentation. The Confluence architecture page showed three virtual networks in a hub-spoke topology. Resource Graph told a different story: six virtual networks, two of them stood up for a regional expansion that had shipped eight months earlier.
The gap wasn’t a security vulnerability. It was evidence that the organisation couldn’t see its own infrastructure reliably. That became a finding on its own — governance, not technical. And the remediation wasn’t a one-time fix to the diagram. It was a documented process for keeping architecture documentation current.
That’s the real cost of stale docs in a regulated environment. Not operational confusion. Evidence of a control gap that auditors treat as structural.
Azure Resource Graph doesn’t drift
Resource Graph is Microsoft’s control plane query API. One real-time, consistent view of every resource across a tenant (properties, configurations, relationships, policy compliance states), all queryable in KQL. The property that matters for documentation: it isn’t a cached representation or a periodic snapshot. It reflects the actual state of Azure Resource Manager at query time.
So you can build documentation that’s always current. Not because someone maintains it. Because it queries the ground truth instead of representing it.
Here’s a basic one. This KQL query returns all virtual networks in a tenant with their address prefixes and subnets:
Resources
| where type == "microsoft.network/virtualnetworks"
| project name, resourceGroup, subscriptionId, location,
addressSpace = properties.addressSpace.addressPrefixes,
subnets = properties.subnets
| order by subscriptionId, resourceGroup, name
Run that on a schedule, write the output to Confluence or a GitHub markdown file, and you have a network topology record that’s accurate at the moment it ran. Nobody has to remember to update it. It doesn’t reflect anyone’s mental model. It reflects what Azure Resource Manager holds.
Same trick for RBAC. A Resource Graph query against the authorizationresources table returns every role assignment in the tenant: the principal, the role definition, the scope. Write it to your documentation target weekly and you’ve got an always-current access model, exactly the kind of record DORA Article 9 and ISO27001 Annex A.9 ask for.
What building this actually looks like
The barrier isn’t technical sophistication. It’s knowing which queries to run, how to shape the output so a human can read it, and how to wire the whole thing in without creating a new maintenance chore.
Four components. Build them in this order.
Start with a query library. KQL covering your documentation surface: network topology, resource inventory by subscription, RBAC assignments, policy compliance state, diagnostic settings coverage, security configuration of the key resource types. Version-control it in the same repository as your IaC.
Then a scheduled execution mechanism. An Azure DevOps pipeline or a GitHub Actions workflow that runs the library on a set schedule (weekly is enough for most governance purposes) and writes the output to your documentation target. Authenticate with a managed identity scoped to Reader. No secrets. No stored credentials.
Then a documentation target. Match the format to where your team actually reads. Engineers live in Confluence? Write to Confluence through the API. Team works in GitHub? Write markdown files to a documentation repository. Whatever you pick, it should be the same place architecture reviews happen and audit evidence is stored.
Last, a change review step. Someone has to look at the weekly output. Not to validate every resource (the queries do that) but to read the delta against last week and confirm the changes were expected. An NSG rule that shows up this week and wasn’t there last week is either an intended change or it’s drift. The review makes the difference visible. Thirty minutes a week for a competent platform engineer.
Initial setup runs two to three days: writing the query library, building the pipeline, wiring up the documentation target. After that, the ongoing cost is the weekly review.
The shift this asks for is treating Azure Resource Manager as the source of your documentation, not the subject of it. The environment isn’t a thing your docs describe. It’s the thing that generates them. Build it that way and accuracy stops being effortful and starts being structural. The docs can’t fall behind, because they’re no longer a separate representation. They’re a formatted export of what’s running.
The short version
- Documentation drift is structural, not a discipline problem. Confluence and Visio have no link to Azure Resource Manager, so they can’t detect that they’re wrong.
- Most environments carry three or four layers: original design, the IaC repo, the Confluence page the auditors see, and Azure Resource Manager itself. Only Resource Manager can’t be wrong.
- Stale documentation becomes a governance finding in its own right. An auditor running a landing zone compliance review reads a diagram that no longer matches the tenant as poor visibility, not just operational mess.
- The working alternative has four parts: a KQL query library, a scheduled pipeline on a Reader-scoped managed identity, a documentation target, and a 30-minute weekly delta review.
FAQ
Why does Azure architecture documentation always go stale? Static tools (Visio, draw.io, Confluence, PowerPoint) have no connection to the Azure control plane. They record the architect’s mental model at one point in time, and the environment keeps changing after that. Nothing inside a Confluence page can detect that it has become wrong. It just accumulates distance from reality.
Is the IaC repository an accurate record of the environment? Closer than a Confluence page, but not definitive. Terraform or Bicep state diverges from actual Azure state when engineers change resources outside the pipeline, when resources are imported without full configuration parity, and when drift accumulates between plan runs. It records what the pipeline last deployed, not what runs now.
How does Azure Resource Graph keep documentation current? It’s Microsoft’s control plane query API, returning a real-time view of every resource, configuration, and policy compliance state at query time. Run a KQL query library on a weekly schedule, write the output to Confluence or a GitHub markdown file, and the record reflects Azure Resource Manager instead of anyone’s memory. That’s the current asset record DORA’s ICT risk framework expects.
What does it take to set up a Resource Graph documentation workflow? Two to three days up front: a version-controlled KQL query library, a scheduled Azure DevOps or GitHub Actions pipeline authenticated with a Reader-scoped managed identity, and a documentation target your team actually reads. After that, the only ongoing cost is a 30-minute weekly review of the delta from the previous run.
(That assessment layer — querying Resource Graph and writing mapped findings straight to GitHub, Jira, or ServiceNow — is the thing I build, PAA, for teams who’d rather not run the pipeline themselves. Link in the comments. The four components above work fine without it, and the discipline matters more than the tool.)
So, honestly: if you queried Resource Graph against your own tenant this week, how far off would your current architecture diagram be? If you genuinely don’t know, that distance is the finding. And it’s why the process, not the diagram, is the thing to fix.