The Azure Well-Architected Operational Excellence Pillar: What Most Teams Skip
The Azure Well-Architected operational excellence pillar exposes manual changes outside IaC, no documented deployment process, and defaults-only monitoring. For platform leads.
The Azure Well-Architected Operational Excellence Pillar: What Most Teams Skip
Can you change this system safely, and will you know what happened when you did? That is the whole operational excellence pillar in one question. And the answer usually arrives as a gap: the part of the environment that lives in code, versus the part that exists because someone clicked through the portal one afternoon. No diagram shows that gap. Nobody can fully account for it.
Teams skip this pillar because nothing forces the issue. Security has breaches. Reliability has outages. Cost has a bill at the end of the month. Operational excellence has none of that. So the work that makes a system operable (infrastructure as code, safe deployment, real observability, written runbooks) gets pushed to next quarter. Then something breaks, and the whole absence comes due at once.
Key takeaways
- Manual changes made outside infrastructure as code are the most common finding here. They create drift the code cannot describe, and the next deployment either reverts them silently or collides with them.
- “We use Bicep” rarely means the whole estate is in Bicep. The assessment finds the resources that got created in the portal and never brought back under code.
- Most environments have monitoring deployed and configured at defaults. Azure Monitor collecting platform metrics, no custom alerts, no thresholds worth acting on, nobody owning the signal.
- Deployment processes are usually undocumented. The person who knows how to ship is the process. That is a single point of failure with a pulse.
- The evidence maps to NIS2 Article 21(2)(f), policies to assess the effectiveness of risk-management measures. You cannot assess effectiveness you never measured.
What the design principles actually ask for
Two questions, really. How does a change reach production? And how would you know if it broke? The pillar wants both answered with a process, not with a person’s name. Operations that are deliberate, repeatable, and observable instead of improvised. The Microsoft Azure Well-Architected Framework breaks this into design principles, and each one maps to a concrete artifact you either have or you don’t.
Adopt infrastructure as code, meaning the environment is defined in version-controlled templates and not assembled by hand. Use safe deployment practices, so changes roll out progressively and you can halt or roll back. Implement observability, collecting the signals that say the system is healthy and acting on them. Automate and document operations, so the knowledge lives in runbooks and code rather than in someone’s head.
None of that is controversial. The findings come from the distance between the principle and how environments actually grow: incrementally, under delivery pressure, with the portal one click away every time the template would have taken longer.
Why the manual-change finding keeps winning
A manual change creates a version of the truth the code has never heard of. The next deployment then has to ignore it or fight it. That is the operational face of configuration drift, and it is the finding I see most consistently.
The story is always roughly the same. The estate is defined in Bicep or Terraform, mostly. A production incident lands at an inconvenient hour. An engineer opens the portal, changes a network security group rule, scales up a database, adds an app setting, whatever it takes. Incident resolved. The change never makes it back into the code. Now the running environment and the source of truth disagree, and nobody wrote down where.
Then it compounds. The next terraform apply may revert the emergency fix and hand you the incident all over again. Or the drift just sits there, invisible, until a region rebuild or a disaster recovery event redeploys from code that no longer matches reality. The assessment catches it by comparing what Azure Resource Graph reports as deployed against what the IaC would produce: resources with no matching template, settings that diverge from what the code declares.
The deeper problem is usually one layer down. No policy stops portal changes in the first place. Azure Policy can deny resource modification outside the deployment identity, and when that guardrail is missing, the portal is an open door. Drift is not a risk at that point. It is a certainty.
Green dashboards that tell you nothing
Defaults-only monitoring is a wall of green that means nothing. Azure Monitor is collecting platform metrics nobody chose, firing no alerts anyone would act on. And it is more common than having no monitoring at all, for a boring reason: an empty monitoring page is obviously wrong, while a busy useless one sails through inspection.
The components are almost always there. Azure Monitor is on. A Log Analytics workspace exists. Application Insights is instrumented. What is missing is the configuration that turns telemetry into awareness. Four gaps show up over and over.
Diagnostic settings on critical resources are absent. Azure Monitor grabs platform-level metrics on its own, but resource logs (what a Key Vault, an Application Gateway, or a firewall is actually doing) only flow when you configure diagnostic settings to stream them to the workspace. The assessment finds critical resources with none configured, which means the data that would have explained an incident was never collected in the first place.
Then there are no alert rules worth the name. Metrics get gathered. Nothing is defined against them. No rule fires when latency blows past its budget, when the failed-request rate climbs, when a dependency starts timing out. The signal is right there. Nothing is watching it.
Where an alert does exist, it often routes nowhere. No action group, no on-call rotation, no escalation. An alert that fires into an empty inbox is theatre.
And Application Insights sits at defaults. Instrumented, but with no custom availability tests, no defined health signal, no distributed tracing across the dependencies that actually fail. Same observability gap the reliability pillar surfaces, seen from the health-modelling angle instead.
The deployment process lives in one person’s head
Ask a plain question. If the one engineer who deploys is on a plane, can anyone else ship a change and recover a failure? In most environments I assess, the honest answer is no. The process and the runbooks are undocumented. They live in the working memory of one or two people, and those people are now a single point of failure.
A documented deployment process spells out how a change moves from commit to production: the pipeline stages, the gates, the approval, the rollback. Safe deployment adds progressive exposure on top: deployment slots in App Service for staged swaps, canary or ring-based rollout, automated rollback when something fails. What I usually find instead is a pipeline that deploys straight to production, no staging gate, and no rollback beyond “redeploy the last good version and hope.”
Runbooks are the other half, the recovery half. Step-by-step responses to failures you can already name: the database failover, the certificate rotation, the dependency outage. Architecture Decision Records sit next to them and capture why the environment is built the way it is. Both go missing together. When they do, the architecture documentation describes a system that no longer exists, and the recovery knowledge walks out the door the day its owner does.
| Design principle | Finding in nearly every assessment | The artifact that should exist |
|---|---|---|
| Adopt infrastructure as code | Resources created in the portal, not in code | Full estate in version-controlled Bicep/Terraform |
| Use safe deployment practices | Direct-to-production pipeline, no rollback | Staged deployment with automated rollback |
| Implement observability | Diagnostic settings absent on critical resources | Resource logs streaming to Log Analytics |
| Implement observability | Metrics collected, no alert rules | Actionable alerts routed to an action group |
| Document operations | Deployment and recovery knowledge in one person’s head | Runbooks and ADRs in version control |
The NIS2 connection nobody makes
NIS2 Article 21(2)(f) asks for policies to assess the effectiveness of cybersecurity risk-management measures. Read that carefully. It is not asking whether you have controls. It is asking whether you know they work. And you cannot know what you do not observe. In regulatory terms, operational excellence is the measurement layer sitting under everything else.
The link is concrete. Knowing a control works needs telemetry: diagnostic logs streaming to a workspace, alerts that fire when the control degrades, a deployment process that records what changed and when. An environment on defaults-only monitoring cannot demonstrate effectiveness, because it is not measuring effectiveness at all. The diagnostic settings, the alert history, the deployment audit trail, those are the proof that the assessment happens in fact and not just on a policy PDF. Operational excellence is the apparatus that lets you show the rest of your posture is real.
Evidence you never had to assemble
A well-operated environment produces its evidence by construction. A version-controlled IaC repository that matches the running estate. A deployment pipeline with an audit trail. Diagnostic settings on every critical resource, alert rules with a firing history, runbooks in source control. That is the material an NIS2 auditor accepts as proof that measures are assessed for effectiveness rather than assumed to work.
Here is the part that matters. None of it gets built for the audit. The IaC repository exists because the team deploys from code. The audit trail exists because the pipeline records every run. The diagnostic logs exist because someone configured observability on purpose. A well-run environment throws off evidence as exhaust, and the absence of that exhaust is itself the finding.
Platform Architecture Authority reads the running estate through Azure Resource Graph, surfaces the gaps (resources outside IaC, missing diagnostic settings, unconfigured alerting) and maps each one to the NIS2 article it touches. It generates the remediation as infrastructure-as-code and policy definitions for you to review and apply. It is read-only. It does not deploy anything itself. A senior platform engineer still decides which alerts genuinely warrant a page and which runbooks the team actually needs. The tool puts those decisions in front of the real configuration instead of a remembered one.
FAQ
What counts as infrastructure as code for this pillar? A version-controlled definition of the environment (Bicep or Terraform) that recreates the resources deterministically. The pillar checks not just that IaC exists but that it matches the running estate. Resources created by hand in the portal, with no matching template, are the gap the assessment surfaces as drift.
Is Azure Monitor enough for observability? No, not on its own. At defaults it collects baseline metrics and stops there. Real observability needs diagnostic settings streaming resource logs to a Log Analytics workspace, alert rules against thresholds that mean something, action groups routing those alerts to an owner, and Application Insights configured with health signals. The platform is necessary. The configuration is what makes it useful.
What is the fastest improvement to make? Configure diagnostic settings on critical resources (Key Vault, firewall, Application Gateway, gateways) to stream to a Log Analytics workspace. Low effort, closes the most common observability gap, and produces the telemetry that both incident response and NIS2 effectiveness assessment lean on. Alerting on that telemetry is the next step.
This is the pillar with no crisis to force it. Which is exactly why it is worth doing before the crisis shows up and asks why nobody saw it coming.