This page is for anyone facing an Azure round, whether you are a fresher with one certification or a senior engineer who runs production on it. Most Azure interviews start with how resources are organised and who can touch them, then move through compute choices, storage and databases, networking and private access, and finish with monitoring, infrastructure as code, disaster recovery and cost. Senior rounds add an incident story and a judgement call under pressure. Each question shows what the interviewer is really checking, the shape of a strong answer and a short answer you can say out loud. Practise them, then swap in your own projects.
Search all questions by round, difficulty and level, or save the ones you want to practise.
Tenant: the Entra ID directory that holds users, groups and apps.
Management groups and subscriptions: groups of subscriptions; a subscription is the billing and quota boundary.
Resource groups and resources: every resource sits in exactly one resource group; settings above flow down.
"At the top is the tenant, which is the Entra ID directory with our users, groups and app identities. Under it you can build a tree of management groups, and each one holds subscriptions. A subscription is where billing and service limits live, and it trusts exactly one tenant. Inside a subscription I create resource groups, and every resource, like a VM or a storage account, belongs to exactly one resource group. Resource groups can't be nested, and the resources in one don't all have to be in the same region. The important part is inheritance: a role assignment or a policy set at a management group flows down to every subscription, group and resource below it. So at my last company we put guardrails on management groups, gave teams their own subscriptions, and grouped resources by application and environment so we could deploy and delete them together."
Treating resource groups as folders that can be nested, or not knowing that permissions and policies inherit down the tree.
RBAC: who can do which actions at which scope; it says nothing about how a resource is configured.
Policy: rules on resource properties such as region, SKU or tags; effects include deny, audit, modify and deploy if not exists.
Together: RBAC lets a team deploy; Policy makes sure what they deploy follows the rules, even for an Owner.
"RBAC answers who can do what, and where. It lets a developer create resources in a resource group, but it says nothing about how those resources are set up. Azure Policy answers what is allowed to exist, whoever creates it. A policy checks a resource's properties, like its region, SKU or tags, and applies an effect: deny the request, just audit it, modify it by adding a missing tag, or deploy something alongside it, like a diagnostic setting. So for a dev subscription I'd give the team Contributor so they can work freely, and assign policies at the management group so they can only use approved regions, every resource needs an owner tag, and storage accounts can't allow public blob access. A deny policy blocks an Owner too, so it's a guardrail, not a permission. I group related policies into an initiative and start new ones in audit mode to see what would break before switching to deny."
Saying Policy decides who can create resources, or that an Owner can simply ignore a deny policy.
Principal: a user, group, service principal or managed identity.
Role definition: a list of allowed actions, such as Reader, Contributor or Owner.
Scope: management group, subscription, resource group or resource; it inherits downward and access is the union of all assignments.
"A role assignment joins three things: a security principal, which is who gets access, a role definition, which is what they can do, and a scope, which is where. So I might assign the Reader role to the support group at the scope of one resource group. Assignments inherit downward, so Reader on a subscription means Reader on everything in it. When someone has several assignments, Azure adds them up, so the effective access is the union of all of them. The built-in roles most people use are Owner, which can do everything including granting access, Contributor, which can manage resources but not grant access, and Reader. One thing that catches people out is that many services split management actions from data actions. Being Contributor on a storage account doesn't by itself give you a data role like Storage Blob Data Reader, which you need to read blobs with your Entra identity."
Thinking a lower-scope assignment can take away access granted higher up, or saying Contributor can hand out access to others.
Entra roles: control the directory: users, groups, app registrations, tenant settings.
Azure roles: control resources at management group, subscription, group or resource scope.
The link: separate by default; a Global Administrator can elevate themselves to manage access at the root scope.
"They're two different systems. Entra ID roles, like Global Administrator or User Administrator, control the directory itself: creating users, resetting passwords, managing groups, app registrations and tenant-wide settings. Azure roles, like Owner, Contributor or Reader, control Azure resources, and they're assigned at a scope such as a subscription or a resource group. By default one doesn't grant the other, so a Global Administrator can't see a single VM until they get an Azure role. There is a bridge though: a Global Administrator can switch on elevated access, which gives them User Access Administrator at the root scope, and from there they can grant themselves anything. That's why I treat Global Administrator as the most sensitive role in the whole estate, keep very few people in it, and use just-in-time activation rather than standing access. For day-to-day resource work, people get Azure roles scoped as narrowly as the job allows."
Saying Global Administrator automatically owns every subscription, or mixing the two role systems up when asked where to grant access.
What it is: an Entra identity Azure manages for a resource; the app asks for tokens, no secret is stored.
System-assigned: created with one resource, deleted with it, used only by it.
User-assigned: a standalone resource you attach to many; survives when they are deleted and can be granted access in advance.
"A managed identity is an identity in Entra ID that Azure creates and rotates for a resource, so my code can get tokens without anyone storing a password or a client secret. In code I just use the Azure SDK's default credential, and on Azure it picks up the managed identity automatically. There are two kinds. A system-assigned identity is switched on for one resource, lives exactly as long as that resource and can only be used by it, which is simple and tidy. A user-assigned identity is its own resource that I can attach to several things. I pick user-assigned when many instances need the same access, like a scale set or a group of function apps, when I want to grant the permissions before the resource even exists so the first deployment doesn't fail, or when resources are recreated often and I don't want to redo role assignments each time."
Describing a managed identity as a stored secret you still rotate, or not knowing that a system-assigned identity is deleted with its resource.
Remove first: use Entra authentication to Azure SQL and storage so there is no password at all.
Key Vault for the rest: store remaining secrets there, not in code or plain settings.
Access: the app's managed identity gets a narrow data role on the vault; settings use Key Vault references.
Safety: soft delete and purge protection on, access logged.
"My first move is to get rid of as many secrets as I can. Azure SQL and storage both accept Entra authentication, so the app's managed identity can connect without any password. For secrets I can't remove, like a third-party API key, I put them in Key Vault. The app gets a managed identity, and I give that identity a narrow role on the vault, like Key Vault Secrets User, so it can read secrets but not change them. In App Service I don't even need code changes: an app setting can be a Key Vault reference, and the platform resolves it using the identity. If I leave the version out of the reference, App Service picks up a rotated secret by itself within a day, with no redeploy. On the vault itself I make sure soft delete and purge protection are on, public access is limited, and diagnostic logs go to our workspace so we can see who read what."
App setting value in App Service:
@Microsoft.KeyVault(SecretUri=https://orders-kv.vault.azure.net/secrets/PaymentApiKey/)
Putting the vault's own access secret in the app config, or giving the app Owner on the vault just to read one secret.
Contain: regenerate the leaked key now; move apps to the other key first if time allows.
Assess: check storage logs and the activity log for access since the leak.
Clean up: remove it from the repo, but treat it as burned regardless.
Prevent: move apps to Entra auth with managed identities and disable shared key access.
"I treat the key as compromised from the moment it went public, because bots scan public repos within minutes. First I check which apps use that key. Storage accounts have two keys, so if the apps can quickly switch to the second key I do that, then regenerate the leaked one. If not, I regenerate it straight away and accept a short break, because an open door to our data is worse. Regenerating also kills any SAS tokens signed with that key. Then I look at what happened in the last hour: storage logs, if diagnostics were on, for reads, writes or deletes from unknown IPs, plus the activity log. I tell the security team early. Removing the commit is still worth doing, but it doesn't make the key safe. The lasting fix is to move the apps to managed identities with data roles and then turn off shared key access, so there's no key left to leak."
Deleting the commit and calling it done, or waiting for a maintenance window before rotating the key.
Understand: what exactly needs changing, on which resource.
Grant narrowly: the smallest role at the smallest scope, time-limited.
Track it: logged, approved, removed after; activity log reviewed.
Improve: a break-glass or just-in-time process so next time is quick and safe.
"I wouldn't say no and walk away, because the issue is real, but I also wouldn't hand out Owner on the whole subscription. I'd ask what exactly they need to change. Usually it's something like restarting an app or changing a setting on one App Service, which Contributor on that one resource, or even a narrower role, covers. Owner also lets someone grant access to others, which nobody needs for a fix. If we have just-in-time access set up, they request that role for a couple of hours with a reason and it expires by itself. If we don't, I grant it manually, set a reminder, and remove it the moment the fix is done. Afterwards I'd check the activity log for what was changed, get the fix into our code so the next deployment doesn't undo it, and push for proper just-in-time access so this is a two-minute process next time."
Granting permanent Owner on the subscription to get the problem off your desk, or blocking an urgent fix on process alone.
Availability set: VMs spread over fault domains and update domains inside one datacenter.
Zones: physically separate datacenters in one region, each with its own power, cooling and network.
Choice: zones protect against a whole datacenter failing; neither protects against losing the region.
"An availability set spreads VMs across fault domains and update domains inside a single datacenter. Fault domains are separate racks with their own power and network switch, so one hardware failure doesn't take out every VM. Update domains make sure planned maintenance reboots only one group at a time. Availability zones go further: they're physically separate datacenters within one region, each with independent power, cooling and networking. If I put one VM in each of three zones behind a zone-redundant load balancer, the app survives an entire datacenter going down, which an availability set can't do. A VM is either in an availability set or pinned to a zone, not both. For new work I default to zones where the region supports them, and I'm clear with the team that neither option covers a full region outage. That needs a second region."
Saying an availability set protects against a datacenter or region failure, or that one VM in a zone is highly available.
Stopped: shut down from the OS; the host is still reserved, so compute is still billed.
Deallocated: stopped from the portal, CLI or API; the hardware is released and compute billing stops.
Still billed: disks and static public IPs cost money either way; non-static IPs can change and the temp disk is wiped.
"Shutting down from inside Windows or Linux leaves the VM in a plain stopped state. Azure still holds the hardware for it, so compute keeps being billed. To stop paying for compute it has to be deallocated, which happens when you press Stop in the portal or run az vm deallocate. That releases the host. The disks stay, so storage is still charged, and a static public IP is still charged too. A few things change on deallocation: any IP address that isn't set to static can change when it starts again, and anything on the temporary disk is gone. For dev and test machines I set the built-in auto-shutdown schedule, which deallocates them every evening, and I'd tell the team to use the portal or CLI rather than the OS shutdown."
az vm deallocate --resource-group rg-dev --name build-vm
az vm get-instance-view -g rg-dev -n build-vm \
--query "instanceView.statuses[?starts_with(code, 'PowerState')].displayStatus" -o tsv
Saying any stopped VM costs nothing, or not knowing the temporary disk is wiped.
Plan: the set of VMs that runs your apps; its tier sets size and features.
Sharing: every app in a plan runs on all its instances and shares CPU and memory.
Up vs out: up changes the tier or size; out adds instances, manually or with autoscale rules.
"An App Service plan is the compute behind one or more web apps. It defines the region, the operating system, the pricing tier and how many instances run. The apps themselves are just what's deployed onto it, and every app in the plan runs on every instance and shares the same CPU and memory. Scaling up means moving to a bigger tier or instance size, which gives each instance more power and unlocks features like deployment slots or autoscale on higher tiers. Scaling out means adding more instances of the same size, and the built-in load balancer spreads traffic across them. For a stateless web app I'd rather scale out, because it also gives me redundancy. One mistake I watch for is packing a heavy background app onto the same plan as a customer-facing site, because a spike in one slows down the other."
Thinking each app on a plan gets its own dedicated servers, or that scaling out needs code changes for a stateless app.
Slot: a live copy of the app with its own hostname, on the same plan.
Swap: deploy to staging, warm it, then swap so production traffic moves to the warmed code.
Settings: mark slot-specific settings as sticky; rollback is swapping back.
"A deployment slot is a separate live instance of the app, with its own hostname, running on the same App Service plan. My usual flow is to deploy the new build to a staging slot, let it start, run smoke tests against the staging URL, and then swap. During a swap, App Service first applies the production slot's settings to the staging instances and warms them up, and only then switches the routing, so users land on code that's already running. That's what removes the cold start and the downtime. The part people get wrong is configuration. Settings like a connection string for a staging database should be marked as deployment slot settings, so they stay with the slot and don't travel with the swap. And rollback is easy: if something looks wrong after the swap, I swap back, because the previous version is still sitting warm in the staging slot."
Not knowing that settings swap unless they are marked sticky, or describing a swap as a redeploy.
Consumption: scales to zero and bills per execution; cold starts and short time limits.
Premium: always-ready instances that avoid cold starts, VNet integration, much longer runs.
Other options: a dedicated App Service plan, or the newer Flex Consumption plan in between.
"On the Consumption plan, the platform adds and removes instances for me and scales to zero when nothing runs, so I only pay for executions. The costs are cold starts, since the first call after idle has to spin up an instance, and a time limit on each run, which is five minutes by default and ten at most. The Premium plan keeps instances warm, which avoids cold starts, supports VNet integration to reach private resources, and allows much longer runs. So Consumption is the wrong choice when an API needs steady low latency, when a function has to reach a database behind a private endpoint, or when a job runs for a long time. In those cases I'd look at Premium, the newer Flex Consumption plan, or a dedicated App Service plan if we already pay for spare capacity. For a long job I'd also consider Durable Functions to break it into steps."
Saying Consumption can run for unlimited time, or not knowing cold starts exist.
Trigger: the one event that starts the function: HTTP call, queue message, timer, blob and so on.
Bindings: declared inputs and outputs so the runtime reads or writes data for you.
Connection: bindings name an app setting, ideally an identity-based connection.
"A trigger is what starts a function, and every function has exactly one: an HTTP request, a message on a queue, a timer, a new blob and so on. Bindings are optional declared connections to other services. An input binding hands the function some data when it starts, and an output binding lets it write somewhere just by setting a value, without me writing the client code. In this Python example the function runs whenever a message lands on the orders queue, and the output binding writes a receipt file into blob storage with a random name. The connection is the name of an app setting, not a connection string in code, and in production I'd point that setting at an identity-based connection so there's no key at all. The runtime also handles retries for the queue trigger, so a message that keeps failing ends up in a poison queue."
import azure.functions as func
app = func.FunctionApp()
@app.queue_trigger(arg_name="msg", queue_name="orders", connection="AzureWebJobsStorage")
@app.blob_output(arg_name="out", path="receipts/{rand-guid}.txt", connection="AzureWebJobsStorage")
def make_receipt(msg: func.QueueMessage, out: func.Out[str]) -> None:
order = msg.get_body().decode("utf-8")
out.set(f"Receipt for order {order}")
Saying a function can have several triggers, or hard-coding connection strings in the function code.
Azure runs: the control plane: API server, etcd, scheduler, their upgrades and availability.
You run: node pools, version upgrades, node image patching, scaling, networking choices.
Integration: Entra sign-in, workload identity for pods, pulling images from a registry with a managed identity.
"AKS gives me a managed control plane. Azure runs the API server, etcd and the scheduler, keeps them available and patches them, and I never log into those machines. What's left is still a lot. I choose and size the node pools, keeping a system pool for cluster components and user pools for our workloads. I decide when to upgrade the Kubernetes version, or set an auto-upgrade channel, and I keep node images patched. I set up scaling at two levels: the horizontal pod autoscaler for pods and the cluster autoscaler for nodes. I pick the network model at creation time, which is hard to change later. And I wire in identity: Entra sign-in for people, workload identity so pods get tokens without secrets, and the AcrPull role so the cluster pulls images from our registry without passwords. Everything running inside the cluster, including our manifests and their resource limits, is also on us."
Saying AKS handles node upgrades and workload security entirely on its own, or not knowing what the control plane is.
Starting point: the app, its dependencies, the constraints and deadline.
Choices: rehost, replatform or rebuild, and why for each part.
Surprises: what broke or cost more than expected.
Result: how it ran after, and what you'd do differently.
"In my last role we moved an internal ordering app off two ageing servers: a .NET web app and a SQL Server database. We had three months, so rebuilding wasn't an option. We moved the web app to App Service rather than VMs, because it needed only small config changes and we stopped patching operating systems. For the database we chose Azure SQL Managed Instance, because the app used SQL Agent jobs and cross-database queries that Azure SQL Database doesn't support well. The surprise was networking. The app called an internal pricing service and an old reporting server that were staying on-premises, and those calls were slow and sometimes failed until we set up VNet integration and a site-to-site VPN properly and fixed DNS resolution in both directions. If I did it again, I'd map every outbound dependency in the first week instead of discovering them in testing."
A migration story with no reasons for the service choices, or one where nothing went wrong and nothing was learned.
Tiers: Hot, Cool, Cold and Archive; cheaper storage means pricier and slower access.
Archive: offline; a blob must be rehydrated, which can take hours, before it can be read.
Automation: lifecycle management rules move or delete blobs by age or last access.
"Blob storage has Hot, Cool, Cold and Archive tiers. As you go down, storing data gets cheaper but reading it gets more expensive. Hot is for data used all the time, Cool and Cold for data read rarely, and Archive for data you keep for compliance and almost never touch. Archive is offline, so before reading a blob I have to rehydrate it to an online tier, and that can take hours. The cooler tiers also have minimum storage periods, so deleting or moving a blob early still costs you as if it stayed the full period. To avoid doing this by hand, I set lifecycle management rules on the storage account. For example, move logs to Cool after thirty days without changes, to Archive after six months, and delete them after the retention period. If access tracking is on, rules can also use last access time instead of last modified time."
Saying Archive blobs can be read instantly, or ignoring early deletion charges when designing lifecycle rules.
LRS and ZRS: three copies in one datacenter, or across three zones in the region.
GRS and GZRS: the same, plus an asynchronous copy in a secondary region.
Read access: RA- versions let you read the secondary; failover is something you start.
"LRS keeps three copies in a single datacenter, so it survives a disk or rack failure but not the datacenter going down. ZRS spreads three copies across availability zones in the region, so it survives losing a whole datacenter. GRS takes LRS and adds an asynchronous copy in the paired secondary region, and GZRS does the same on top of ZRS. The RA versions let you read from the secondary endpoint at any time, which is useful for a read-only fallback. The key detail is that geo-replication is asynchronous, so if the primary region fails, the latest writes may not have reached the secondary yet. And failing over is an action you or Microsoft trigger, not something instant. So I pick by what the data can survive: scratch or easily rebuilt data on LRS, production app data on ZRS, and data we must keep through a regional disaster on GZRS."
Treating redundancy as a backup against accidental deletion, or claiming geo-replication loses no data.
Azure SQL: managed SQL Server engine; relations, joins, transactions across tables, ad hoc reporting.
Cosmos DB: NoSQL, partitioned, low-latency reads and writes at scale, global distribution.
Deciding questions: shape of data, known queries, scale and regions, the team's skills.
"I start with the data and the queries. Azure SQL Database is the SQL Server engine as a managed service, so it's the natural fit when data is relational, when we need joins and transactions across several tables, and when people will run reports and ad hoc queries we can't predict yet. Cosmos DB is a partitioned NoSQL database. It shines when access patterns are known and simple, like reading a user's profile or a device's latest readings by key, when we need very low latency at large scale, or when we need copies in several regions with writes close to users. The price of that is design effort up front: choosing a partition key, modelling documents around queries, and picking a consistency level. If the team is unsure, I'd usually start on Azure SQL, because it's forgiving of changing requirements, and move hot, high-volume paths to Cosmos DB once we know them."
Choosing Cosmos DB just because it scales, without mentioning partition key design or the loss of easy joins.
How it works: items with the same key share a logical partition; throughput and storage spread across physical partitions.
Good key: many distinct values, even spread of reads and writes, used in most query filters.
Failure modes: hot partitions get throttled; cross-partition queries cost more; changing the key means migrating.
"In Cosmos DB, every item with the same partition key value lives in the same logical partition, and those are spread across physical partitions that share the container's throughput. So the key decides how evenly load spreads and how expensive queries are. A good key has lots of distinct values, spreads reads and writes evenly, and appears in the filter of most queries so they hit one partition. For an orders container, order date is a bad key because all of today's writes land on one value and that partition gets throttled with 429 errors. Order ID spreads writes perfectly but makes 'show me this customer's orders' a query across every partition. Customer ID is usually the sweet spot: many values, and the most common query is by customer. If a few huge customers break that, I'd look at a hierarchical key like customer then month. And I choose carefully, because changing it later means moving the data to a new container."
Picking a timestamp or a low-cardinality field like status as the key, or saying the key can simply be edited later.
VNet and subnets: a private address space split into subnets for tiers.
NSG: stateful allow and deny rules on port, protocol and source; attach to a subnet or a network card.
Evaluation: lowest priority number wins, first match stops; traffic must pass both NSGs if both exist.
"A virtual network is my private address space in a region, and I split it into subnets, usually one per tier, like web, app and data. A network security group is a list of allow and deny rules based on source, destination, port and protocol, and I attach it to a subnet, a network card, or both. Each rule has a priority number, and Azure checks them from the lowest number up and stops at the first match. Below my rules sit default rules I can't delete but can override: traffic inside the VNet is allowed, inbound from the internet is denied. NSGs are stateful, so if I allow a request in, the reply goes back out automatically. If there's an NSG on the subnet and another on the network card, inbound traffic has to be allowed by both. To keep rules readable I use service tags and application security groups instead of raw IP ranges."
Saying the highest priority number wins, or forgetting that NSGs on the subnet and the network card both apply.
Service endpoint: the subnet reaches the service over the Azure backbone; the service keeps its public address and allows that subnet.
Private endpoint: a private IP in your subnet mapped to one specific resource; public access can be turned off.
DNS: a private DNS zone must make the service name resolve to that private IP.
Reach: private endpoints work from peered networks and on-premises over VPN or ExpressRoute.
"A service endpoint is a setting on a subnet. Traffic from that subnet to, say, Azure Storage travels over the Azure backbone and carries the subnet's identity, so the storage firewall can allow just that subnet. But the service still has a public address, and it doesn't help traffic coming from on-premises. A private endpoint puts a network card with a private IP inside my subnet, mapped to one specific resource, like one storage account. Then I can turn off public network access completely, and it's reachable from peered VNets and from on-premises over VPN or ExpressRoute. Because it maps to one resource, it also limits data being copied out to some other account. The extra work is DNS: I need a private DNS zone, like privatelink.blob.core.windows.net, linked to the VNet, so the normal hostname resolves to the private IP. When a private endpoint doesn't work, it's almost always DNS."
Saying a service endpoint gives the service a private IP, or setting up a private endpoint and ignoring DNS.
Cause: peering connects exactly two VNets and is not transitive.
Hub and spoke: spokes peer only to a hub holding the firewall and the VPN or ExpressRoute gateway.
Routing: route tables on spokes send traffic to the hub firewall, which allows spoke-to-spoke flows it should.
At scale: Azure Virtual WAN manages the hub for you.
"Peering links exactly two virtual networks and isn't transitive, so A talking to B and B talking to C doesn't let A reach C. You could peer everything with everything, but that becomes a mess quickly. The usual design is hub and spoke. The hub VNet holds shared services: Azure Firewall or a network appliance, and the VPN or ExpressRoute gateway to on-premises. Each application VNet is a spoke that peers only with the hub. On the spokes I add route tables that send traffic for other spokes and for the internet to the firewall's private IP, and the firewall rules decide which spokes may talk. I enable gateway transit on the hub peering so spokes can use the hub's gateway to reach on-premises without their own. For a large or multi-region estate, Virtual WAN does the same pattern as a managed service, which saves maintaining route tables by hand."
Assuming peering is transitive, or suggesting a full mesh of peerings as the long-term answer.
Load Balancer: layer 4, regional, TCP and UDP, very fast, no understanding of HTTP.
Application Gateway: layer 7, regional; path routing, TLS termination, web application firewall.
Front Door: layer 7, global at the edge; routes users to the nearest healthy region, WAF and caching.
Traffic Manager: DNS-based, global, any protocol; only answers DNS, never proxies traffic.
"I split them by layer and by scope. Azure Load Balancer works at layer 4 inside one region: it spreads TCP or UDP connections across VMs and knows nothing about URLs, so I use it for non-HTTP traffic or internal tiers. Application Gateway is layer 7 and regional, so it can route by path or hostname, terminate TLS and run a web application firewall in front of VMs or AKS. Front Door is layer 7 and global: users connect to the nearest edge location, and it routes them to the closest healthy backend in any region, with WAF and caching. Traffic Manager is global too but only DNS-based. It hands out the address of a healthy endpoint and steps out, so it works for any protocol, but failover waits on DNS caching. A common setup is Front Door globally with Application Gateway or an internal load balancer in each region."
Calling Traffic Manager a proxy, or putting a layer 4 load balancer in front when path-based routing is required.
Azure Monitor: the umbrella for metrics, logs and alerts.
Log Analytics: the workspace where logs land, queried with KQL; App Insights stores app telemetry in it.
Getting logs in: diagnostic settings per resource; the Azure Monitor agent for VM guest logs.
Alerts: metric or log query alerts that fire action groups.
"Azure Monitor is the umbrella. It collects platform metrics automatically, which are numbers like CPU or request count, and it's where alerts live. Logs go into a Log Analytics workspace, and I query them with KQL. Application Insights is the part that watches my own app: requests, dependencies, exceptions and traces, and it stores that data in the workspace too. The gotcha is that most resource logs aren't collected until you add a diagnostic setting on each resource that sends them to the workspace, so I enforce that with Azure Policy. For VMs, the Azure Monitor agent with a data collection rule brings in guest logs and performance counters. Then I build alerts on metrics or on log queries, wired to action groups that page the on-call engineer. This query, for example, shows which operations started failing in the last hour."
AppRequests
| where TimeGenerated > ago(1h)
| where Success == false
| summarize failures = count() by OperationName, bin(TimeGenerated, 5m)
| order by failures desc
Assuming every resource's logs are in the workspace without diagnostic settings, or having no answer for how anyone is alerted.
Bicep: a cleaner language that compiles to ARM JSON; Resource Manager does the deploying.
Declarative and idempotent: you describe the end state; redeploying changes only what differs.
Modes and preview: incremental by default, complete deletes what is missing; what-if shows changes first.
"Every create or change in Azure goes through Azure Resource Manager. ARM templates are the JSON way of describing resources to it, and Bicep is a much more readable language that compiles down to that same JSON, so anything ARM can deploy, Bicep can. Both are declarative: I describe the end state and Resource Manager works out what to create or update. That makes deployments idempotent, so if I deploy the same template twice, the second run finds nothing different and changes nothing. By default deployments run in incremental mode, which leaves alone any resources in the group that aren't in the template. Complete mode deletes them, so I only use it very deliberately. Before touching production I run what-if, which lists what would be created, changed or deleted. I break bigger setups into modules, one per component, and deploy them through a pipeline rather than from laptops."
param location string = resourceGroup().location
param accountName string
resource logs 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: accountName
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_ZRS'
}
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
}
}
Saying redeploying a template creates duplicate resources, or using complete mode without knowing it deletes things.
Situation: what broke, who was affected, how you found out.
Diagnosis: the signals you used: metrics, logs, activity log, Resource Health.
Fix: the short-term fix and the lasting one.
After: alert, runbook or design change so it doesn't recur.
"At my last company our checkout API started timing out one afternoon. Application Insights showed the failures were all on calls to our Azure SQL database, and the database metrics showed CPU pinned at the top of its limit. The activity log had no config changes, so I looked at Query Store and found one query whose plan had changed after a statistics update, and it was now scanning a large table. As a short-term fix I forced the previous good plan, and response times recovered within minutes. I posted updates in the incident channel every fifteen minutes so support could answer customers. Afterwards we added the missing index, set up a log alert on database CPU and long-running queries so we'd hear before customers did, and wrote a short runbook for plan regressions. The lesson I took was to check the activity log and Resource Health first, so you quickly know whether it was us or the platform."
A story with no data behind the diagnosis, or one that ends at the quick fix with nothing changed afterwards.
Problem: the pain the portal was causing, like drift or broken copies of environments.
Approach: start small, import or rebuild existing resources, deploy through a pipeline.
People: how you got the team to change habits.
Result: what got better, and what you would change.
"At my last company, dev, test and production had been built by hand, and they'd drifted apart. A release failed in production because an app setting existed in test but nobody had added it to prod. I proposed Bicep, and started small with one application's resource group rather than the whole estate. I wrote modules for App Service, SQL and Key Vault, ran what-if against each environment to see the drift, and fixed the differences in code. Deployments moved into our pipeline, with what-if output posted on every pull request so reviewers could see changes. The hard part was habits, so I paired with each engineer on their first change and made the pipeline the only identity with write access to production. After a couple of months, new environments took an hour instead of days, and we stopped having config surprises in releases."
Forcing a big-bang rewrite of all infrastructure at once, or leaving people with portal write access to production afterwards.
Targets first: agree RTO and RPO with the business; they decide active-active versus warm standby.
Zone level: zone-redundant App Service plan, zone-redundant Azure SQL, ZRS storage.
Region level: a failover group to a second region, GZRS for data, the same stack deployed by IaC there.
Traffic and practice: Front Door with health probes; rehearse failover regularly.
"I'd start by asking how long we can be down and how much data we can lose, the RTO and RPO, because that decides the cost. For zone failures, I make every layer zone-redundant: App Service plan across zones with enough instances, Azure SQL with zone redundancy, and storage on ZRS. That covers a datacenter going down with no action from us. For a region outage, I deploy the same stack in a second region from the same Bicep, keep the app tier small there as a warm standby, and put Azure SQL in an auto-failover group so the app connects through one listener name that follows the primary. Storage uses GZRS, and secrets live in a vault in each region. Front Door sits in front with health probes and sends users to the healthy region. Because replication is asynchronous, I'd be honest that RPO isn't zero. And we rehearse failover every quarter, because an untested plan usually fails."
Jumping to active-active everywhere without asking for recovery targets, or ignoring that geo-replication is asynchronous.
See it: Cost Management by service and tag, budgets with alerts, tags enforced by policy.
Remove waste: idle and oversized resources, orphaned disks and IPs, dev machines left running.
Pay less for steady load: reservations or savings plans, existing licences, spot for interruptible work.
Design: autoscale, storage lifecycle rules, log ingestion trimmed.
"First I'd get visibility. In Cost Management I break spend down by service, resource group and tag, and if tags are patchy I enforce owner and environment tags with Azure Policy so every cost has a name on it. I set budgets with alerts so we hear about spikes in days, not at month end. Then I go after waste: Advisor's right-sizing hints, unattached disks, unused public IPs, forgotten test environments, and dev VMs left running overnight, which auto-shutdown fixes. Next, for load that's steady all year, I'd look at reservations or a savings plan, and at bringing existing Windows Server or SQL Server licences we already own. Spot VMs suit batch work that can be interrupted. Finally design changes: autoscale instead of sizing for the peak, lifecycle rules for old blobs, and trimming noisy logs going into Log Analytics. I'd avoid cutting redundancy on production just to save money without the business agreeing."
Jumping straight to buying reservations before removing waste, or cutting production redundancy quietly to save money.
Now: declare an incident; check each service's own recovery options and backups.
Rebuild: redeploy infrastructure from code, then restore data.
Prevent: delete locks on production, least-privilege roles, backups kept outside the group.
"First I'd declare an incident and be honest about impact. There's no recycle bin for a resource group, so recovery depends on each service. Key Vault has soft delete, so the vault and its secrets can be recovered. Databases may be restorable from backups, depending on how they were set up, and a deleted storage account can sometimes be recovered for a short time if nothing new took its name. Whatever can't be recovered, we rebuild. If the infrastructure is in Bicep, I redeploy the group from the pipeline, then restore data into it and check the app end to end. If it was built by hand, this is where it really hurts. To stop it happening again, I put a delete lock on every production resource group, so even an Owner has to remove the lock first. I'd also cut back who has write access to production, keep backups in a separate subscription, and make deletions go through the pipeline."
Assuming Azure can undo a resource group deletion on request, or blaming the teammate instead of fixing access and guardrails.
ClapAssist is an AI interview assistant for Mac and Windows. It listens to the interview on your computer and shows you what to say, in short lines you can read while you talk. Your resume and notes are never stored on our servers. It stays out of screen share on every plan; only you can see it.