A cloud engineer candidate at a 200-person fintech in Austin lost a final-round Azure loop in March 2026 over one follow-up: what actually happens to every VM, NSG, and storage account inside a resource group if someone runs az group delete --yes without a lock in place. She'd nailed every ARM template question up to that point. Then the interviewer asked what stops that command from wiping out production by accident, and the answer just wasn't there.
Azure still trails AWS for enterprise adoption, but not by much. In a survey of 753 cloud decision-makers this year, 83 percent of enterprises said they're running some or significant workloads on AWS, against 79 percent on Azure, according to Flexera's 2026 State of the Cloud Report (Flexera, 2026). A four-point gap is close enough that most cloud and DevOps roles in 2026 expect you to know Azure cold, not as a fallback for missing an AWS offer.
Here's an opinion that might be wrong: I think Bicep questions get asked more often than they should. Microsoft has pushed Bicep hard since 2021, and it's a genuinely cleaner authoring experience than raw ARM JSON (Microsoft Learn, Bicep overview). But most enterprise Azure estates still running production infrastructure in 2026 have thousands of lines of ARM JSON from 2019 that nobody's rewritten and nobody wants to touch. Testing a candidate purely on Bicep syntax skips the harder, more common skill: reading a legacy ARM template you didn't write and safely changing one parameter without breaking the other forty resources hanging off it.
This page covers the Azure interview questions that show up across real 2026 loops for cloud and DevOps roles: core Resource Manager concepts, VMs, storage accounts, Entra ID and identity, networking, Azure Functions, App Service, AKS, infrastructure as code, monitoring, and a handful of scenario questions that mix two or three topics into one problem.
Core Azure concepts: regions, resource groups, and Resource Manager
Every Azure loop opens here, even for senior candidates. It reads as throat-clearing, but a shaky answer on resource groups is usually the first thing that makes an interviewer start probing harder on everything that follows.
Easy questions
9A region is a physical location with one or more datacenters, East US or West Europe, for example. Availability zones are physically separate datacenters within a single region, each with independent power, cooling, and networking, so a zone-redundant deployment survives one datacenter going dark.
A region pair is two regions Microsoft has matched for disaster recovery, generally in the same geography (a couple of exceptions exist). Microsoft staggers planned platform maintenance so it doesn't hit both halves of a pair in the same window, which is the actual reason region pairs exist beyond just "two places far apart."
A resource group is a logical container for resources that share a lifecycle, not a physical boundary. Resources inside it don't have to share a region, a VM in East US and a storage account in West Europe can sit in the same group without issue.
What it enforces concretely is deletion and access scope. Delete the group and everything inside goes with it, no per-resource confirmation. What resource groups actually give you is one scope for RBAC, tagging, and cost reporting, not a network or geography boundary.
Managed disks are handled entirely by Azure, storage placement, redundancy, and IOPS scaling included, you just pick a size and a tier. Unmanaged disks require you to manage the underlying storage account yourself, which means watching IOPS limits per account so one busy VM doesn't quietly throttle every other VM sharing that account.
Microsoft's been steering people toward managed disks since 2017, and that per-account IOPS ceiling is why almost nobody chooses unmanaged for a new build today.
Blob storage holds unstructured data, images, backups, log files, anything you'd otherwise dump on a filesystem. Queue storage is a simple message queue for decoupling components, one part of an app drops a message, a worker picks it up later.
Table storage is a NoSQL key-value store for structured data that doesn't need relational joins. File storage exposes an SMB or NFS file share you can mount directly, useful for lift-and-shift apps that expect a real network drive rather than an API call.
No, that's exactly what Azure Files is for. It exposes a genuine SMB or NFS file share you mount like any on-prem file server, unlike blob storage, which is accessed through REST calls and SDKs rather than a mapped drive.
Reach for Azure Files for lift-and-shift apps that read and write through normal filesystem calls, and reach for blob storage for anything built API-first, images, backups, log archives. Azure NetApp Files sits a tier above both, for workloads that need enterprise NFS performance neither blob nor standard Azure Files can hit, though it's rare that a workload genuinely needs it.
An NSG is a stateful firewall, a set of allow and deny rules evaluated by priority number, that filters traffic in and out of resources. You can attach one to a subnet, a network interface, or both at once.
Attached at both levels, traffic has to clear both rule sets, whichever one denies first wins. A rule that looks fine on the NIC can still get blocked by a stricter subnet-level NSG a candidate forgot was even there.
A public Load Balancer distributes inbound internet traffic across a backend pool of VMs or scale set instances, and it's also what gives those VMs outbound internet access by default through SNAT. An internal Load Balancer only ever gets a private IP inside a VNet, used for a mid-tier or database layer that only the app tier in front of it should reach at all.
Both operate at Layer 4, TCP and UDP only, with no inspection of HTTP headers or paths. Anything a routing decision needs to make based on URL path or hostname belongs to Application Gateway instead, not to Load Balancer.
A trigger is what starts an execution, an HTTP request, a new blob, a queue message, a timer, every function has exactly one. Bindings are optional, declarative connections to other services for input or output, without you writing SDK calls yourself.
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "queue",
"direction": "out",
"name": "outputQueueItem",
"queueName": "outqueue",
"connection": "AzureWebJobsStorage"
}
]
}A function can bind straight to a Cosmos DB document or drop a message onto a Service Bus queue just by declaring it here, no client SDK code required.
A node is a single VM running the Kubernetes agent and hosting pods. A node pool is a group of nodes sharing the same VM size and configuration. Every AKS cluster needs at least one system node pool for core cluster components, and you can add user node pools with different VM sizes, GPU-enabled nodes alongside cheaper burstable ones, for example.
Medium questions
33ARM is the deployment and management layer every Azure interaction goes through, whether it comes from the portal, the CLI, PowerShell, Terraform, or a raw REST call. Every one of those tools ends up hitting the same ARM API underneath (Microsoft Learn, Azure Resource Manager overview).
What that actually buys you: consistent RBAC enforcement no matter which access path someone used, and templated, repeatable deployments instead of clicking the same eleven settings by hand every time a new environment gets spun up. A minimal ARM template just needs a schema, a content version, and a resources array:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[parameters('storageAccountName')]",
"location": "[resourceGroup().location]",
"sku": { "name": "Standard_LRS" },
"kind": "StorageV2"
}
]
}A subscription is the billing boundary and also a scale boundary, quotas like maximum VNets per region or maximum resource groups apply per subscription, not per tenant. A management group sits above subscriptions purely for governance, letting one Azure Policy assignment or one RBAC role apply across a dozen subscriptions at once instead of copying the same setting into each one by hand.
Multiple subscriptions become necessary once billing genuinely needs to separate, dev versus prod, or one subscription per business unit for clean chargeback, or once a workload hits a subscription-level quota that support won't just raise on request. A four-level hierarchy, tenant root group, one management group per environment, subscription, resource group, is common on paper, though most mid-size companies get by fine with two or three subscriptions total.
An Availability Set groups VMs across fault domains and update domains within a single datacenter, so a hardware failure or a planned maintenance window in one domain doesn't take out every VM at once. An Availability Zone spreads VMs across physically separate datacenters in the same region entirely.
Zones protect against losing a whole datacenter. Sets only protect against losing a rack or a maintenance window inside one. You can't mix the two on a single VM, an instance is either zonal or in a set, never both at once.
A VM Scale Set manages a group of identical, load-balanced VMs as one resource, and it can scale the count up or down automatically off a metric like CPU or queue length. Reach for one the moment you need more than a handful of interchangeable VMs behind a load balancer, or any autoscaling requirement at all.
Provisioning VMs by hand still works fine for a single always-on box, a jump server or a one-off batch job, but it falls apart the second "how many do we need" stops being a fixed number.
Start with the family, not the size. General-purpose Dv5 balances CPU and memory for typical app servers, Ev5 adds more memory per core for databases and in-memory caches, Fv2 is compute-optimized for CPU-bound batch work, and the N-series bolts on GPUs for ML training or rendering.
Size within the family based on measured usage, not a guess. A burstable B-series instance is often the cheaper right answer for a dev box that sits idle most of the day and only needs headroom for occasional spikes. Right-sizing after two or three weeks of real Azure Monitor data beats guessing on day one almost every time.
On Linux, cloud-init runs on first boot and can install packages, write config files, and run commands, all from one YAML file passed in at VM creation time. On Windows, or for anything that needs to run again after the VM already exists, the Custom Script Extension downloads and executes a script from a URL or an inline command instead.
az vm create
--resource-group prod-app-rg
--name web-vm01
--image Ubuntu2204
--custom-data cloud-init.ymlThe two aren't interchangeable. Cloud-init only fires once, on the very first boot. Ongoing configuration drift after day one needs a real configuration tool, Ansible or a similar agent, not another custom-data payload rerun against a VM that's already live.
A Spot VM runs on Azure's unused capacity at a discount that can run 60 to 90 percent off list price, but Azure can evict it with as little as 30 seconds of notice the moment that capacity is needed for a regular pay-as-you-go customer. An eviction policy controls what happens next, Deallocate keeps the disk around for a later restart, Delete removes the VM outright, and an optional max price caps what you'll pay before Azure evicts on cost alone.
Good fit for batch jobs, CI runners, and stateless workers that can pick up wherever they left off. Wrong fit for anything stateful or customer-facing, 30 seconds isn't enough runway to fail over gracefully.
Standard Premium SSD bundles a fixed IOPS and throughput tier to a fixed disk size, want more performance and you're paying for a bigger disk whether the extra space gets used or not. Premium SSD v2 breaks that link entirely, capacity, IOPS, and throughput get set independently and can change with no downtime, which matters for a database that needs high IOPS against a fairly small amount of storage.
Ultra Disk goes further still, sub-millisecond latency and IOPS up to 400,000 per disk, built for the handful of workloads, SAP HANA, high-transaction SQL, where even Premium SSD v2's ceiling isn't enough. Most production workloads never actually need Ultra Disk. Reaching for it by default instead of profiling real IOPS first is a common way teams overspend on disk.
LRS keeps three copies within a single datacenter, cheapest option, zero protection if that datacenter goes down. ZRS spreads those three copies across availability zones in the same region instead.
GRS adds a second, geographically distant region with asynchronous replication, but that secondary copy isn't readable until Microsoft actually fails over to it. RA-GRS is GRS plus a read-only endpoint against the secondary region at all times, which is usually the one people actually want when they say "geo-redundant" and don't realize plain GRS doesn't let you read the backup copy during normal operation.
Hot costs the most per GB stored and the least per read, meant for data touched constantly. Cool and cold step storage cost down while raising the cost per access, meant for data touched monthly or less. Archive is by far the cheapest tier for storage, but data isn't instantly available, rehydrating a blob out of archive can take hours, not seconds.
{
"rules": [
{
"name": "moveOldLogsToArchive",
"type": "Lifecycle",
"definition": {
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 90 }
}
},
"filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["logs/"] }
}
}
]
}A lifecycle management policy like this one automates the tier transitions on a schedule instead of relying on someone to remember to move old data every quarter, which in practice never happens consistently.
Microsoft renamed Azure Active Directory to Microsoft Entra ID in 2023, same service, new name, so don't be thrown if an interviewer uses either term. Entra ID is a cloud identity provider built around REST APIs, OAuth, and SAML, it doesn't support classic on-prem concepts like Group Policy or NTLM.
Active Directory Domain Services is the traditional on-prem directory, LDAP and Kerberos included. Azure's managed, cloud-hosted version of that classic directory service exists for lift-and-shift apps that still need it, and it's a genuinely different product from Entra ID, not a renamed version of the same thing.
Role assignments made higher up cascade down through everything beneath them. Assign Contributor at a management group and every team touching any subscription under it inherits Contributor, whether that's what anyone intended or not.
The safer default is assigning roles as low in the hierarchy as the job actually requires, resource group or single-resource scope, rather than reaching for subscription-level access because it's the option people notice first in the portal.
A managed identity only exists for the lifetime of the Azure resource it's attached to, and nothing outside Azure can authenticate as it. A service principal is a standalone identity that works from anywhere, a GitHub Actions runner, a script on someone's laptop, an on-prem server, anything authenticating to Azure from outside Azure's own resources.
Rule of thumb: if the thing authenticating is itself an Azure resource, use a managed identity and skip credential management entirely. If it's external to Azure, a service principal with a certificate or a federated credential (avoid a plain client secret where the option exists) is the only path left.
When the closest built-in, Contributor say, grants delete rights on a resource type a support engineer should never touch, or when a team needs to restart VMs but not resize or remove them, no built-in role draws that exact line. A custom role definition lists specific allowed actions, specific denied actions, and the scopes it's assignable at.
{
"Name": "VM Restart Operator",
"IsCustom": true,
"Actions": [
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/read"
],
"NotActions": [],
"AssignableScopes": ["/subscriptions/<sub-id>/resourceGroups/prod-app-rg"]
}Custom roles earn their setup cost once the same narrow permission set gets assigned across teams repeatedly. For a one-off, scoping a built-in role tightly to a single resource group is usually less long-term maintenance than owning a custom role definition.
Every update to a secret creates a new version rather than overwriting the old one, and each version carries its own identifier and its own expiration date. Apps referencing the secret without pinning to a specific version pick up the latest one automatically on their next read, no code change or redeploy required.
Key Vault can trigger rotation on a schedule and call an Azure Function to generate and write the new value, and for supported resource types like storage account keys there's a built-in rotation policy that handles the whole cycle with no custom code at all. Old versions stay retrievable rather than vanishing, useful for the one time a rotation breaks something and the previous value needs pulling back immediately while someone debugs.
Azure Monitor watches performance and availability, CPU, latency, error rates. Defender for Cloud watches for security misconfiguration and active threats specifically, a storage account left open to the public internet, a VM missing months of patches, a login from a country nobody on the team has ever traveled to, and it rolls all of it into a secure score you can track improving or slipping over time.
The free tier gives recommendations and the secure score. The paid tier, priced per resource type, adds actual threat detection, alerting on a brute-force attempt against a VM or an unusual Key Vault access pattern rather than only flagging static misconfiguration. Most teams run the free tier everywhere and turn on paid protection only for the resource types actually facing the internet.
Application Gateway operates at Layer 7 and can route based on URL path or hostname, terminate SSL, and run a Web Application Firewall in front of the backend, none of which Load Balancer does since it only ever sees TCP and UDP packets. Send /api/* to one backend pool and /images/* to another from the same public entry point, something Load Balancer simply has no concept of.
They're not always either-or. A common pattern puts Application Gateway in front for HTTP-aware routing and WAF, with an internal Load Balancer behind it distributing traffic to a tier that doesn't need any Layer 7 logic at all. Picking Application Gateway purely for the WAF feature, with no path-based routing need in sight, is a fine reason on its own for anything internet-facing.
Default system routes handle traffic between subnets in the same VNet, to peered VNets, and out to the internet with zero configuration. A UDR overrides that default the moment traffic needs to go somewhere the system route wouldn't send it, forcing all outbound traffic through a network virtual appliance or firewall instead of straight out to the internet, for example.
az network route-table route create
--resource-group prod-network-rg
--route-table-name prod-rt
--name force-through-firewall
--address-prefix 0.0.0.0/0
--next-hop-type VirtualAppliance
--next-hop-ip-address 10.0.1.4The classic mistake: a UDR routes everything through a firewall appliance, then someone adds a new subnet and forgets to associate the route table with it, and that subnet's traffic quietly bypasses the firewall entirely with no error or warning anywhere in sight.
Consumption plan scales to zero and you pay per execution, but an idle function has to spin up a fresh instance on the next request, that's cold start, and it can add anywhere from a few hundred milliseconds to several seconds depending on runtime and package size.
Premium plan keeps a configurable number of instances warm at all times, eliminating cold start at a fixed baseline cost. Dedicated plan runs functions on VMs you're already paying for, so cold start isn't a concern at all, but you lose the pay-per-execution economics that make Consumption attractive for spiky, low-volume workloads.
A deployment slot is a separate, fully live instance of your App Service, staging next to production, each with its own hostname and settings. Swapping two slots doesn't copy files around, it's a virtual IP and configuration swap, so the instance that was "staging" a second ago is serving production traffic instantly, and vice versa.
App settings marked "sticky" don't swap, which is exactly how you keep a slot's own connection string or feature flag from following it into production by mistake. (Side note: the portal's blade names rarely match the actual ARM resource type, App Service is Microsoft.Web/sites everywhere else, which trips up more scripting exercises than it should.)
An autoscale setting on the App Service plan defines rules keyed to a metric, CPU percentage or HTTP queue length are the common ones, with a scale-out rule (add an instance when CPU passes 70 percent for 10 minutes) and a scale-in rule (remove one below 30 percent), plus a minimum and maximum instance count so it can never scale to zero or run away unbounded.
Cooldown periods matter here as much as the thresholds do. Skip one and a metric bouncing around the threshold triggers a scale-out and a scale-in every few minutes, instances flapping up and down instead of settling, which costs more and helps nobody.
For pulling images from Azure Container Registry, AKS can attach directly using managed identity integration, no static credential or imagePullSecret needed at all. For pods that need to reach other Azure services, workload identity federation lets a Kubernetes service account exchange its token for an Entra ID token scoped to exactly what that workload needs, rather than a cluster-wide credential every pod could theoretically read.
HPA scales the number of pod replicas for a deployment based on CPU, memory, or a custom metric, operating entirely inside the cluster with no idea whether the nodes underneath actually have room for more pods. Cluster Autoscaler operates one layer down, adding or removing real VM nodes in a node pool once pods can't be scheduled because every existing node is full, or removing nodes that have sat underutilized long enough.
They work together, not in competition. HPA decides more pods are needed, scheduling fails because there's no room, Cluster Autoscaler notices the unschedulable pods and adds a node, and the stuck pods finally land. Running HPA without Cluster Autoscaler on a fixed-size node pool just means pods pile up in Pending once capacity runs out.
Application Gateway Ingress Controller wires an existing Application Gateway directly into the cluster as its ingress, so WAF, SSL termination, and Azure-native monitoring come from infrastructure the team may already run elsewhere, not a new component living inside the cluster. NGINX ingress runs as pods inside the cluster itself, more portable across clouds, with the larger community and more examples to copy from.
My honest take: if Application Gateway isn't already sitting in the environment for something else, standing one up just to get AGIC is more moving parts than most clusters actually need. NGINX ingress is the less opinionated default the moment AKS is the only thing in the picture.
Cleaner syntax mainly. No bracket-matching, no giant expressions like [reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')))] buried three parameters deep. Bicep also gives you real modules, type-checking at authoring time instead of failing mid-deployment, and loops over resource collections without copy-pasting the same block five times.
Functionally the two deploy identically, Bicep is just a transpiler down to the same ARM JSON. If you'd asked me in 2021 whether Bicep would replace ARM JSON outright by now, I'd have said obviously. It hasn't, not even close. Most of what's actually running in production predates Bicep entirely.
Idempotent means running the same deployment twice produces the same end state, not two of everything. Deploy a Bicep file defining one storage account, run it again unchanged, and Azure recognizes the resource already matches and does nothing.
That's what makes IaC safe to run on every merge instead of only on the first deploy. Worth knowing too: incremental mode, the default, leaves other resources in the group alone. Complete mode deletes anything in the resource group that isn't defined in the template, which is a real footgun if someone flips that flag without realizing what's sitting in the group already.
Once a template starts mixing genuinely unrelated concerns, networking, compute, and a database, in one file, or once two environments need to share most of the same resources with a few parameters different. A module lets you reference a separate Bicep file as a reusable unit with its own inputs and outputs, similar to calling a function instead of pasting the same fifty lines into every environment's template.
module storageModule 'modules/storage.bicep' = {
name: 'storageDeploy'
params: {
storageAccountName: 'stprodapp001'
location: resourceGroup().location
sku: 'Standard_ZRS'
}
}
output storageAccountId string = storageModule.outputs.storageIdThe what-if command runs the deployment engine's comparison logic without touching a single resource, showing exactly which resources it would create, modify, or delete, and which specific properties would change on each one.
az deployment group what-if
--resource-group prod-app-rg
--template-file main.bicep
--parameters main.parameters.jsonIt catches the deployment that looks safe on paper but would actually recreate a resource, some property changes force a delete-and-recreate instead of an in-place update, and what-if is the only way to see that coming before it happens to something stateful, a database with real data sitting in it, instead of finding out after the fact.
Azure Monitor is the umbrella platform, metrics, logs, and alerts across every Azure resource. Log Analytics is the query engine and workspace underneath it, where logs actually get stored and queried using Kusto Query Language.
Application Insights is the application-performance layer built on top of that same workspace, request rates, dependency call latency, exception traces, tied to your code rather than infrastructure metrics.
An Azure Monitor metric alert rule scoped to that VM, condition set on the Percentage CPU metric with a 90 threshold, evaluated over a 10-minute window, wired to an action group for email or a webhook.
az monitor metrics alert create
--name high-cpu-prod-vm01
--resource-group prod-app-rg
--scopes /subscriptions/<sub-id>/resourceGroups/prod-app-rg/providers/Microsoft.Compute/virtualMachines/prod-vm01
--condition "avg Percentage CPU > 90"
--window-size 10m
--evaluation-frequency 5m
--action high-cpu-action-groupDiagnostic settings on any resource route its logs and metrics into a Log Analytics workspace. From there, Kusto Query Language is what turns raw log rows into something queryable, filterable, and chartable, closer to a SQL SELECT than a static dashboard tile.
AppRequests
| where TimestampTime > ago(1h)
| where ResultCode == "500"
| summarize FailureCount = count() by bin(TimestampTime, 5m), Name
| order by TimestampTime descThat query surfaces exactly which endpoint is throwing 500s in five-minute buckets over the last hour, the kind of question a default metrics chart can't answer without KQL doing the actual filtering and grouping underneath it. Saved queries turn into workbooks, and workbooks turn into the dashboard a team actually checks every morning instead of the default blade nobody bothers to customize.
A Reserved Instance commits to a specific VM size in a specific region for one or three years for up to 72 percent off, the biggest discount of the three, but it's locked to that exact size, switch VM families later and the reservation stops matching what's actually running. A Savings Plan commits to a dollar amount of compute spend per hour instead of a specific size, a smaller discount than a matched Reserved Instance but flexible enough to shift across VM families, regions, and even container instances without losing the discount.
Spot, covered earlier for VMs specifically, isn't a commitment at all, no upfront spend, just whatever unused capacity is available at whatever price Azure sets that hour, eviction as the tradeoff. Stable, predictable production workloads fit Reserved Instances or Savings Plans. Anything that tolerates interruption fits Spot, and most production estates end up running a mix of all three rather than betting everything on one pricing model. I don't have solid numbers on how Savings Plans perform for container instances specifically, most of what I've seen written up is VM-focused.
Azure Advisor's cost recommendations surface the boring, high-impact stuff automatically, VMs running under 5 percent average CPU that could downsize a tier or two, disks attached to nothing at all, and Reserved Instance purchase suggestions based on actual usage over the last 30 days.
az advisor recommendation list
--category Cost
--output tableCost Management's own analysis view breaks spend down by resource group, tag, or meter, so a creeping increase gets attributed to something specific instead of staying a mystery line on the invoice. In practice, forgotten dev and test resources that never got torn down after a project wrapped are the single most common source of unexplained cost growth, well ahead of anything tied to actual production traffic.
Hard questions
13Every resource inside gets deleted along with it, no per-item confirmation, even resources you didn't personally create and might not remember are sitting in there. Azure doesn't ask "are you sure" per resource, only once for the group.
The two real safeguards: a resource lock, CanNotDelete or ReadOnly, set at the resource group or resource level, and RBAC scoped tightly instead of handing out Contributor at the subscription level by default. A lock on the group is the one that would've actually caught the scenario from the top of this page.
az lock create
--name dont-delete-prod-rg
--resource-group prod-app-rg
--lock-type CanNotDelete
--notes "Production resources, remove lock before deleting anything"A storage account key grants full control over every container and every blob in the entire account, and it doesn't expire until someone rotates it manually. Handing that to a vendor for one container means they could read, write, or delete anything else in the account too, indefinitely, until someone remembers to rotate the key.
A shared access signature scopes access down to exactly what's needed, one container, read-only, expiring in 24 hours, and can be revoked early by rotating the stored access policy it's tied to, no need to touch the account key at all. User delegation SAS goes further still, tying the token to an Entra ID identity instead of the account key, so audit logs show a named principal rather than an anonymous holder of a shared secret.
A managed identity is an identity Azure creates and manages for a resource, a VM, a Function App, an App Service, so that resource can authenticate to other Azure services with no credential ever stored in code or config. System-assigned identities live and die with the resource; user-assigned identities exist independently and can attach to multiple resources at once.
The real security win is that there's nothing to leak. A hardcoded connection string in app settings is a standing secret that outlives the deployment. A managed identity's token gets issued on demand and expires, and there's nothing sitting in a repo or a config blade for someone to accidentally commit.
PIM makes a privileged role, Owner, Global Administrator, User Access Administrator, eligible rather than permanently active. A user eligible for a role has zero standing access until they explicitly activate it, usually with an approval step and a written justification, and the activation expires on its own after a set window, an hour, eight hours, whatever the policy allows.
The security win is that a compromised account sitting idle carries no privileged access worth stealing, there's nothing to use without also tripping the approval workflow and the audit trail behind it. Permanent Owner assignments are exactly the standing access PIM exists to eliminate, and most compliance frameworks in 2026 flag a permanent privileged role assignment as a finding on its own.
Access policies are the original, vault-scoped model, permissions get set directly on the vault resource itself with no inheritance from resource group or subscription-level role assignments. Azure RBAC integration lets Key Vault permissions flow through the same role assignment system as every other Azure resource, inherited from resource group or subscription scope exactly like a storage account or a VM would be.
Microsoft's own guidance points new vaults toward RBAC now, mainly for consistency, one permission model across the whole estate instead of Key Vault being the one resource type that works differently from everything else. Vaults created before RBAC integration existed are often still running on access policies, and migrating a live vault between the two models mid-flight is disruptive enough that most teams leave the old ones alone rather than migrate purely for consistency's sake.
VNet peering connects two VNets directly over Microsoft's backbone with no public internet hop, cheapest and lowest-latency choice when both VNets are already in Azure. A VPN gateway works when one side is on-premises or in another cloud, encrypted but with more latency and a per-hour gateway cost.
ExpressRoute is the private, dedicated-circuit option for high-throughput, low-latency connections to on-prem, at real cost and a provisioning lead time measured in weeks. For two Azure VNets specifically, peering is almost always the right first answer unless there's a specific reason, overlapping address spaces, routing through a shared firewall appliance, to reach for something heavier.
A Service Endpoint extends your VNet's identity to a service like a storage account or SQL database, traffic still travels Microsoft's backbone instead of the public internet, but the service itself keeps its public IP and public DNS name, just with network rules restricting which VNets can reach it. A Private Endpoint goes further and assigns the service an actual private IP inside your VNet, with its own network interface, so it shows up as if it were just another resource sitting on your subnet.
The practical difference shows up in hybrid scenarios. A Private Endpoint reaches from on-prem over ExpressRoute or VPN with no extra configuration since it's just a private IP. A Service Endpoint can't, it only works for traffic starting inside the same VNet or a peered one, which rules it out for exactly the hybrid setups a Private Endpoint handles without issue.
Plain Azure Functions are stateless and short-lived by design, each execution starts fresh with no memory of the last one. Durable Functions add an orchestration layer that can pause for hours or days, wait on external events, and fan out to dozens of parallel activities and fan back in, all while checkpointing state so an orchestration survives the host restarting mid-run.
The classic use case is a multi-step approval workflow. Submit, wait for a human sign-off that might take three days, then continue, something a plain function has no mechanism to express on its own.
App Service fits a traditional always-on web app or API where you want managed scaling, deployment slots, and custom domains without touching Kubernetes. Azure Functions fits event-driven, bursty, or scheduled work where paying only for execution time matters more than keeping an instance warm.
AKS is the answer once you need fine-grained control over the runtime itself, multiple services with different resource profiles, custom networking, sidecar patterns, or you're already running Kubernetes elsewhere and want one operational model everywhere. My honest read: most teams reach for AKS a step earlier than they need to. App Service or Functions handles a surprising amount of real production traffic without the ongoing cluster-maintenance tax.
Check the storage account's transaction metrics first, not just capacity. A spike in read or write transaction count with no change in stored data usually means something's hammering it with requests rather than storing more.
az monitor metrics list
--resource /subscriptions/<sub-id>/resourceGroups/prod-app-rg/providers/Microsoft.Storage/storageAccounts/stprodapp001
--metric Transactions
--interval PT1H
--aggregation TotalCommon culprits: a retry loop somewhere gone wrong hammering the same blob repeatedly, a new consumer accidentally pointed at production instead of a test container, or a lifecycle management policy that stopped tiering anything to cool storage, so everything's billing at hot-tier rates.
Lift-and-shift onto App Service or a set of VMs first, not a rewrite, the goal here is minimal downtime, not architectural purity. Use deployment slots to warm up the new environment fully before cutover, swap once health checks pass, and keep the old environment running for a rollback window instead of tearing it down the moment the swap looks fine.
Database migration is usually the actual risk, not the app tier. Azure Database Migration Service, or a read-replica-then-cutover pattern, keeps write downtime down to the seconds it takes to flip a connection string, rather than hours of a full export and import.
Start with kubectl describe pod, the events section usually shows OOMKilled directly along with the exit code. Then check whether the memory limit is actually undersized for real load, kubectl top pod against the same pod, or Container Insights in Log Analytics if metrics-server access is limited, shows actual usage against the configured limit.
It's not always a limits problem. A memory leak that grows unbounded will eventually blow past any limit you set, so watching whether usage climbs steadily over hours versus spiking under one specific request pattern tells you whether to raise the limit or go find the leak.
Start with the App Service diagnostics blade and actual application logs, az webapp log tail streams them live and usually shows whether the app is throwing an unhandled exception or just timing out. A 502 from App Service specifically often means the worker process crashed or restarted mid-request, so check the health-check and container-restart events under Diagnose and Solve Problems before assuming it's a networking issue.
If logs look clean, check whether the 502s correlate with scale-out events or slot swaps. A cold instance spinning up under load is a common, boring cause that gets missed while everyone's staring at application code.
How to prepare for an Azure interview in 2026
Skip another slide deck of service names and pricing tiers. Build one small thing end to end instead: a resource group with a VNet, one VM or App Service instance, a storage account, and an NSG that locks down anything public-facing. Then break it on purpose. Delete a lock and see what actually happens, swap a deployment slot and watch which settings follow it and which stay behind, misconfigure an NSG priority and trace why the rule you expected to win didn't. Fixing your own mistakes teaches the mental model faster than reading about it does.
Across mock interview sessions run through LastRoundAI's cloud and DevOps track, the stumble that shows up most often isn't a missing service name. It's candidates who know AKS conceptually, pods, deployments, services, but freeze the moment a follow-up gets AKS-specific: how does this cluster actually authenticate to the container registry without a static credential sitting in a secret somewhere. That one trips up candidates who've clearly used Kubernetes, just not Azure's identity plumbing around it. I don't have good numbers on how this holds up for pure data-platform roles, Synapse, Data Factory, this page is written from an infrastructure and DevOps angle, not a data-engineering one.
Get the reps in before the real thing
Reading answers to Azure interview questions is not the same as defending them live once someone changes one variable on you mid-answer. LastRoundAI's mock interview mode runs cloud and DevOps rounds with real-time follow-up questions instead of a static bank, and the free plan includes 15 credits a month that reset monthly rather than stockpiling. Starter is $19/mo if fifteen sessions a month isn't enough.
If the slower part of the job hunt is actually getting in front of enough cloud and DevOps roles rather than passing the interview once you land one, Auto-Apply queues tailored applications for your review, 10 a month on the free plan, up to 400 a month on the Ultimate plan, and every application sits in a review queue until you approve it. Nothing goes out on your behalf without you looking at it first.
Questions about either product go to contact@lastroundai.com, that's the only inbox we check.

