Microsoft Azure Services and Architecture Questions
Microsoft Azure's core service catalog and architectural patterns: Virtual Machines, managed Kubernetes (AKS), App Service and Azure Functions, Storage accounts and managed disks, Azure SQL and Cosmos DB, VNets with hybrid connectivity and global load balancing, Microsoft Entra ID and RBAC, and Key Vault secrets and encryption. Covers Azure service selection, infrastructure as code (ARM, Bicep, Terraform), observability with Azure Monitor and Kusto queries, cost governance and Azure Policy, the Azure Well-Architected design principles, and hybrid management via Azure Arc, common in enterprise Azure estates. For provider-agnostic trade-offs, see the cross-cloud entries.
Design a disaster recovery strategy for stateful microservices running in AKS where primary data stores are Azure Database for PostgreSQL and Cosmos DB. Requirements: RTO = 1 hour, RPO = 15 minutes, GDPR constraints, and minimal data loss. Cover replication strategies, backup frequency, failover orchestration, DNS changes, and application-level considerations (leader elections, idempotency).
Sample Answer
Direct answer
Meet a 1-hour recovery time objective (RTO, how long you are down) and 15-minute recovery point objective (RPO, how much data you can afford to lose) with an active-passive design across two regions: near-continuous replication for both data stores, automated failover orchestration for the predictable steps, and one deliberate human approval gate before the system starts accepting writes in the new region, since an automatic split-brain across two write-capable regions is a worse outcome than a slightly slower failover.
Structured elaboration
Replication and backups.
- Azure Database for PostgreSQL (Flexible Server): enable geo-redundant backup with point-in-time restore (PITR, restoring to any second within the retention window) and configure a cross-region read replica using write-ahead log (WAL) streaming. Monitor replica lag continuously; a 15-minute RPO means the replica must never fall more than a few minutes behind in steady state, leaving headroom for the promotion itself.
- Cosmos DB (Azure's globally distributed NoSQL database service): enable multi-region writes for the collections the application cannot function without, and single-region write with automatic failover for the rest, since multi-write regions trade some conflict-resolution complexity for a near-zero RPO on the collections that matter most. Use continuous backup mode so point-in-time restore is available as a second line of defense behind replication.
Failover orchestration, and where automation stops. Automate everything that is purely mechanical and reversible: promoting the PostgreSQL replica, updating connection strings, scaling up the standby AKS (Azure Kubernetes Service) deployments from a warm, low-replica-count standby to full capacity, and re-pointing DNS. Keep one deliberate manual approval gate at the point of no return, meaning the moment you accept new writes in the failover region, because an automatic trigger on a flaky health probe can promote a region unnecessarily and now you have two regions that both believe they are primary. This automation-versus-manual boundary is the single most important design decision in the runbook: automate detection and staging, require a human (or a second, independent health signal) to approve the actual cutover.
DNS and traffic cutover. Use Azure Traffic Manager or Azure Front Door with a low time-to-live (TTL, how long a client caches a DNS answer) of around 60 seconds on the failover-relevant record, and drive the endpoint priority change from the same runbook that promotes the databases, so DNS and data promotion happen in the same automated sequence rather than as two people doing two things at slightly different times.
flowchart TD
A[Health probes detect region outage] --> B[Automated: stage standby AKS + validate replica lag]
B --> C{Human approval gate}
C -->|approved| D[Promote PostgreSQL replica]
D --> E[Update Cosmos DB write region if needed]
E --> FF[Scale AKS deployments to full capacity]
FF --> G[Update Traffic Manager or Front Door priority]
G --> H[Run smoke tests, remove maintenance flag]
C -->|rejected or false alarm| I[Stand down, log incident]
Application-level considerations. Leader election (using the Kubernetes Lease application programming interface or a coordination service) ensures only one instance issues writes that must be serialized, which matters most in the seconds right after failover when both regions' pods may briefly be starting up. Idempotency keys on every mutating request mean a retried request during promotion does not double-process an order or a payment. Design for GDPR (the EU's General Data Protection Regulation) by keeping both regions inside the EU and building an erasure workflow that deletes from the primary and propagates the deletion through replication rather than only deleting locally.
Worked example
Suppose the region outage starts at 09:00. Health probes and synthetic transactions confirm the outage by 09:02. The automated stage step scales the standby AKS deployment from zero to a warm state and confirms PostgreSQL replica lag was 3 minutes at last check, well inside the 15-minute RPO budget. The human approval gate fires a page; an on-call engineer confirms this is a real regional event (not a transient probe flap) by 09:07 and approves. Promotion, DNS update, and full AKS scale-out complete by 09:20. Smoke tests pass by 09:25. Total time from outage to serving traffic: 25 minutes, comfortably inside the 1-hour RTO, with the 5-to-7-minute human confirmation step being the only non-automated segment of the timeline.
Trade-offs & pitfalls
Synchronous replication would give a near-zero RPO but adds write latency to every transaction in steady state, which is rarely worth it unless the workload is the smallest, highest-value slice of the data. Multi-region writes on Cosmos DB reduce failover time to nearly zero but introduce conflict resolution the application must handle explicitly; do not enable it broadly "just in case." The single biggest pitfall is fully automating the cutover trigger: a health-probe flap or a single-region networking blip should never be able to unilaterally promote a secondary region, because reversing an unwanted promotion is far more disruptive than the extra few minutes a human confirmation step costs.
You must migrate a 50 TB on-premises SQL Server estate that uses linked databases and SQL Agent jobs to Azure with minimal downtime. Propose a migration approach considering lift-and-shift vs re-platform vs refactor, target (Managed Instance vs SQL on VM), appropriate data migration tools (DMS, transactional replication, log shipping, Azure Data Box), and a cutover plan.
Sample Answer
Direct answer
Treat this as a re-platform, not a lift-and-shift: move the estate to Azure SQL Managed Instance (MI) so linked databases and SQL Agent jobs keep working with near-zero code change, and use a combination of an initial bulk seed plus continuous replication so the 50 terabyte (TB) size never forces a long outage. Only fall back to SQL Server on an Azure virtual machine (VM) for the handful of databases that use a feature MI genuinely does not support.
Structured elaboration
Strategy. Lift-and-shift (moving the VM as-is) is fastest but leaves you patching an operating system forever; refactor (rewriting around cloud-native services) is the most work for a 50 TB estate with legacy Agent jobs and is not justified here. Re-platform to MI is the middle path: Microsoft takes over patching and backups, and MI still supports cross-database ownership chaining, linked servers, and SQL Agent, which is exactly what this estate depends on.
Target selection. Default every database to MI. Route to SQL on VM only where you find a specific incompatibility (an unsupported CLR (Common Language Runtime, .NET code running inside the database engine) assembly referencing a Windows dynamic-link library, a legacy driver requiring OS-level access) during compatibility assessment with Data Migration Assistant.
Migration tooling, compared directly. Three tools do overlapping but not identical jobs:
- Azure Database Migration Service (DMS) performs an online migration: it takes a full backup, restores it to the target, then continuously applies transaction log changes until you are ready to cut over. It is the default choice for most databases in the estate because it needs the least manual setup.
- Transactional replication (publisher/subscriber, with on-premises SQL Server as the publisher and MI as a subscriber) is the fallback when DMS's online mode does not support a database's specific configuration (very high write rates, certain unsupported objects). It gives finer control over what gets replicated and lets the source stay live and writable throughout, but it means manually standing up and monitoring a replication topology, and it does not replicate schema changes made mid-migration by default.
- Log shipping is the simplest and most bandwidth-tolerant option for the largest, most static databases: seed once (see Data Box below), then apply transaction log backups on a schedule to keep the target within minutes of the source, accepting a short, planned final cutover to apply the last logs.
- Azure Data Box solves the bandwidth problem, not the freshness problem: for a 50 TB initial seed, if the network link cannot move that volume inside the change window, ship the data on Data Box hardware and let DMS or log shipping handle only the incremental catch-up afterward.
Pick DMS as the default, transactional replication for the databases DMS cannot handle online, log shipping for the largest static databases, and Data Box only to solve the initial-seed bandwidth problem, not as an ongoing sync mechanism.
Agent jobs and linked databases. Script every SQL Agent job to Transact-SQL (T-SQL) and re-create it on the target MI, since Agent job definitions do not migrate automatically with DMS. Validate job credentials, proxies, and any cross-database three-part-name references before cutover, not after.
Worked example
Suppose the estate has 40 databases: 35 small-to-medium databases with normal write rates, 3 very large (8 to 12 TB) databases with high transaction volume, and 2 databases with linked-server calls between them for a nightly reconciliation job. Plan: run DMS online migration for the 35 normal databases in parallel migration waves. For the 3 large, high-write databases, seed via Data Box (network transfer of 8 to 12 TB each would likely exceed the maintenance window on typical enterprise links) then use transactional replication to keep them within minutes of the source until cutover, since DMS's online mode has tighter throughput ceilings on very high write volumes. For the 2 linked databases, migrate them together in the same wave so the linked-server relationship never points across an on-premises/Azure boundary mid-migration. Cutover for each wave: freeze writes on a scheduled maintenance window, apply the final transaction log or let replication catch up, redirect application connection strings, run smoke tests, and only then decommission the source for that wave, keeping it in a read-only standby state for a defined rollback window before final decommission.
Trade-offs & pitfalls
The pitfall this question is really testing is treating "minimal downtime" as a single migration-tool decision instead of a per-database one: forcing every database through the same tool because it is simpler to operate usually means the largest, highest-write databases blow the maintenance window. The second pitfall is forgetting Agent jobs and linked-server credentials until the cutover weekend; script and validate them during the rehearsal migration, not the production one. Finally, always keep the source writable and intact for a short, explicit rollback window; a cutover with no path back is a bet, not a plan.
Compare Azure Functions hosting plans: Consumption, Premium, and Dedicated (App Service Plan). For a bursty event-driven API with sensitivity to cold starts and a need for VNet access, which hosting plan would you recommend and what mitigations would you apply to reduce cold-start impact?
Sample Answer
Direct answer
For a bursty, event-driven API that is sensitive to cold starts and needs Virtual Network (VNet) access, recommend Flex Consumption, the current recommended plan for new serverless Azure Functions apps, sized with a small number of always-ready instances to cover baseline traffic. If the workload's language or region isn't yet supported on Flex Consumption, fall back to Premium with a minimum instance count of at least 1. The older Consumption plan is disqualified outright: it doesn't support outbound virtual network integration at all, so it can't meet the VNet requirement no matter how cold starts are handled.
Hosting plan comparison
| Plan | Scaling model | Cold starts | VNet | Cost model |
|---|---|---|---|---|
| Consumption (legacy) | Fully event-driven autoscale from zero | Expected on every scale-from-zero instance, with no always-ready option to avoid it | Not supported: the plan has no outbound VNet integration at all | Pay per execution only |
| Flex Consumption (current default) | Event-driven autoscale, plus configurable "always ready" instances | Eliminated for traffic within the always-ready capacity; burst instances beyond it still cold-start | Native, no extra hop | Pay per execution, plus cost for always-ready instances |
| Premium (Elastic Premium) | Pre-warmed instances (a configurable minimum count) plus autoscale for bursts | Eliminated on the pre-warmed capacity | Full support | Billed for pre-warmed capacity continuously, plus scale-out usage |
| Dedicated (App Service Plan) | Runs on VM capacity you already pay for; not autoscaled for event volume unless you add App Service autoscale rules | None, as long as "Always On" is set | Full support | Continuous VM cost regardless of function invocations; idle capacity is wasted spend |
Cold-start mitigations, regardless of plan
- Keep the deployment package small and the dependency tree lean; fewer assemblies or packages to load on a cold instance means a shorter cold start.
- Keep the function app's own startup code (static constructors, dependency-injection container setup) minimal, since it reruns on every cold start.
- The legacy Consumption plan cannot be paired with VNet integration at all, since the plan doesn't support it; move VNet-plus-cold-start-sensitive workloads to Flex Consumption or Premium instead.
- If stuck on Consumption for now, a scheduled timer-triggered "warm-up" ping is a workaround, not a fix; treat it as temporary.
Worked example
A payment-webhook receiver expects a steady 5 requests/second baseline and bursts to 200 requests/second for a few minutes at a time, with a hard requirement that outbound calls to a Key Vault (Azure's managed service for storing secrets, keys, and certificates) and a database go through a private VNet. Configure Flex Consumption with an instance memory size of 2048 MB and an always-ready instance count sized to comfortably absorb the 5 requests/second baseline, so steady traffic never cold-starts. Let the 200 requests/second burst scale out on top of that; the newly spun-up burst instances, not the always-ready ones, absorb the cold-start cost. If even burst traffic can't tolerate a cold start, size the always-ready count closer to the burst peak instead, which trades cost for latency consistency.
Trade-offs and pitfalls
- Premium and Flex Consumption both cost money at zero traffic once you configure pre-warmed or always-ready capacity, so "serverless" here is a spectrum, not a binary; sizing that capacity to the true peak defeats the pay-per-use benefit that made a consumption model attractive in the first place.
- Sizing always-ready or minimum instances too low reproduces the exact cold-start problem the plan change was meant to solve; validate against real traffic percentiles, not the average.
- Legacy Consumption has no outbound VNet integration at all, so it is disqualified immediately for any VNet-plus-cold-start-sensitive scenario, not merely a slower option; don't reach for it out of familiarity.
Design an Azure architecture for a healthcare customer subject to HIPAA that processes PHI. Cover encryption at rest/in-transit, Key Vault with HSM, identity enforcement (PIM, conditional access), network segmentation, logging and auditing retention, and Azure Policy/Azure Blueprints for continuous compliance. Identify residual risks and mitigations.
Sample Answer
Direct answer
HIPAA doesn't certify Azure services directly; it obligates the covered entity (or business associate) to implement specific administrative, physical, and technical safeguards, and Azure's role is to sign a Business Associate Agreement (BAA) and provide services capable of supporting those safeguards. The architecture has to satisfy the Security Rule's requirements end to end (encryption, access control, audit logging, retention) and be continuously enforced, not just correct on day one, which is why Azure Policy and Blueprints matter as much as the initial design.
Controls by requirement
- Encryption at rest: Azure Storage and Azure SQL both encrypt at rest by default (platform-managed keys), but for PHI (protected health information) specifically, use customer-managed keys (CMK) stored in Key Vault with HSM-backed keys (HSM: Hardware Security Module, a dedicated, tamper-resistant hardware device that generates and stores the key so it is never exposed as plain data in software memory) (Managed HSM or Premium-tier Key Vault), so the organization controls key lifecycle and can prove it independently of Microsoft. This matters for HIPAA's technical safeguard requirement to control access to ePHI, since key control is a genuine additional access boundary, not just a compliance checkbox.
- Encryption in transit: enforce TLS 1.2+ on every endpoint (Storage, SQL, App Service) and disable any legacy protocol versions at the resource level, not just at the application layer, so a misconfigured client can't silently negotiate a weaker protocol.
- Identity enforcement: PIM (Privileged Identity Management) for any standing access to systems touching PHI, so admin access is time-boxed and justified rather than persistent, and Conditional Access requiring MFA and a compliant device for any access to PHI-handling resources. Role assignments should follow least privilege at the resource level (a specific database, not the whole subscription).
- Network segmentation: PHI-handling resources live in their own subnet(s) with NSGs (Network Security Groups: rule sets, similar to a firewall, that allow or block network traffic in and out of a subnet or network interface) default-denying anything not explicitly required, PaaS services (Storage, SQL) reachable only via Private Endpoint, and no PHI-handling resource exposed with a public endpoint at all. A hub-spoke topology with Azure Firewall inspecting anything crossing the boundary gives one place to enforce and log this.
- Logging and audit retention: HIPAA's audit control requirement means every access to ePHI needs to be logged with enough detail to reconstruct who accessed what, when. Route diagnostic logs (Key Vault
AuditEvent, SQL Auditing, Storage access logs, Entra ID sign-in/audit logs, Entra ID being Microsoft's cloud identity service, the directory of an organization's users, groups, and their sign-ins) into a Log Analytics workspace with a retention period that meets the organization's actual policy (commonly 6 years for HIPAA-relevant records, which is a business/legal retention decision to confirm with compliance, not an engineering default to assume). Immutable/append-only storage for the audit trail itself (a separate, more locked-down storage account with a retention/legal-hold policy) protects against the audit log being tampered with by the same access it's supposed to catch. - Continuous compliance: Azure Policy definitions enforcing the above as code (deny creation of a storage account without CMK encryption in the PHI resource group, deny a public IP on anything tagged as PHI-handling, require diagnostic settings on every new resource in scope) so drift is caught and blocked at deployment time, not discovered in a quarterly audit. Azure Blueprints is in Microsoft's retirement window (phased retirement began July 31, 2026, full retirement January 31, 2027), so it is not the right choice for a new design today. Package this policy set plus the RBAC (role-based access control: granting permissions by assigning a role, such as Contributor or a custom role, to a user or identity at a specific scope, instead of handing out one-off individual permissions)/network baseline using Deployment Stacks (Microsoft's recommended replacement, which groups a set of resources for coordinated lifecycle management and can deny out-of-stack changes to protect against drift) plus Template Specs (versioned, shareable ARM/Bicep templates for the underlying resources), giving the same "repeatable, compliant-from-creation artifact" outcome Blueprints used to provide, without building on a service that is being phased out.
Worked example
A patient-portal application stores PHI in Azure SQL Database. The database has TDE (Transparent Data Encryption) using a customer-managed key from a Managed HSM, is reachable only via Private Endpoint from the app tier's subnet, and has SQL Auditing enabled, writing to a Log Analytics workspace with a 7-year retention policy set at the workspace level (chosen conservatively above the commonly-cited 6-year figure, per the organization's own legal guidance, which is the kind of number that has to come from compliance, not be assumed by engineering). An Azure Policy assignment at the PHI resource group's scope denies deployment of any SQL Database without Transparent Data Encryption enabled and without a diagnostic setting configured, so a developer cannot accidentally stand up a non-compliant database even if they skip the documented process. Access to the database's admin role requires PIM activation with a business justification and a 4-hour maximum window, and Conditional Access blocks any access attempt from a non-compliant device regardless of MFA status.
Residual risks and mitigations
- A compliant architecture does not guarantee compliant application code. SQL injection, over-broad application-level data access (the app's own service account can read more PHI than any single user session needs), or PHI logged into application logs by mistake are all real risks Azure Policy and network controls don't catch; application-level security review and data-loss-prevention scanning of logs are necessary complements.
- Key control is only as strong as who can manage the Key Vault/Managed HSM itself. If the same broadly-privileged admins who could access the data can also manage the encryption keys, CMK provides less real separation than it appears to; consider a separate, more restricted admin group for key management specifically.
- BAA scope gaps: confirm the BAA and the organization's own configuration actually cover every Azure service in the architecture that touches PHI, including ones added later (a new service added to the pipeline six months in that isn't covered by the existing compliance review is a common, quiet source of exposure).
- Backup and disaster recovery copies of PHI need the same encryption, access control, and audit requirements as the primary; a backup that's encrypted with a different key management story, or restorable by a broader set of admins than the primary, is a real and commonly-missed gap.
Trade-offs and pitfalls
The most consequential mistake is treating HIPAA compliance as a one-time architecture review rather than an enforced, continuously-checked policy set; an architecture that was compliant at launch drifts the first time someone adds a resource outside the documented pipeline, which is exactly what Azure Policy's deny-by-default assignments are for. The second is assuming "Azure has a BAA available" means every service is automatically in scope and covered; the BAA covers services the organization has actually configured and attested to using appropriately, and using an out-of-scope service for PHI without updating that assessment is a compliance gap regardless of the underlying technical security.
You operate an API behind an Azure Standard Load Balancer backed by a VM Scale Set. Traffic spikes predictably every day for 30 minutes and reaches 10x baseline. Design an autoscaling strategy to meet latency SLOs while controlling cost: specify scheduled scaling, metric-based policies, cooldowns, warm-up/instance-provisioning considerations, and minimum/maximum instance count choices.
Sample Answer
Direct answer
Because the spike is predictable, same time, same duration, every day, lead with scheduled scaling to pre-provision the extra capacity a few minutes before the spike starts, and layer metric-based autoscaling on top as a safety net for load that does not match the schedule exactly. Relying on reactive metric-based scaling alone carries an inherent lag, detect, then boot new instances, then wait for them to become healthy, which is exactly the latency-SLO (service-level objective) risk a known, recurring spike lets you design around instead of merely react to.
Structured elaboration
Scheduled scaling. Configure a recurring autoscale profile that raises the minimum instance count from baseline to a pre-calculated "spike-ready" count starting 10 to 15 minutes before the daily spike begins, enough lead time for new instances to provision, boot, and pass health probes before real traffic arrives, and lowers it back after the spike ends. This turns the spike from something the system reacts to into something it already expects.
Metric-based policy as the safety net. Layer CPU and request-queue-length-based scale-out rules on top of the scheduled baseline. A queue-length trigger, the depth of a Service Bus or Storage Queue in front of the API if requests are buffered, or the scale set's own request-queue metric if synchronous, is often a more direct signal of "customers are waiting" than CPU, since CPU can look fine while requests queue up behind a slow downstream dependency. This catches a spike that is 20 percent larger than yesterday's, or starts 5 minutes early, without over-provisioning for that uncertainty in the schedule itself.
Cooldowns and instance protection. Use a short scale-out cooldown, the minimum time between the last scale action and the next, so the system keeps adding capacity if a spike keeps growing, and a longer scale-in cooldown so instances are not removed the moment load dips for one measurement interval only to be needed back 90 seconds later. The classic failure mode this whole design avoids is thrashing, rapid scale-out followed by scale-in followed by scale-out again. Instance protection is the specific guard against it: mark newly scaled-out instances with scale-in protection for a grace period after they join, so the next autoscaler evaluation cannot immediately remove an instance that just finished warming up and has not yet taken meaningful traffic.
Warm-up and instance-provisioning considerations. A scale set instance is not ready for real traffic the moment it boots; it needs the OS to finish booting, the application to start, and, if the app does any lazy initialization such as loading a cache or warming a connection pool, that too, before it should receive production requests. Configure the load balancer's health probe against an application-level endpoint that only returns success after warm-up completes, not an OS-level "is a socket open" check, otherwise the autoscaler and load balancer both believe capacity exists several seconds or more before it actually does, precisely when latency SLOs get breached during a scale event.
Minimum and maximum instance counts. Set the daily baseline minimum to handle normal off-peak traffic with headroom for a single-instance failure, never a minimum of 1, which has zero fault tolerance. Set the scheduled spike-ready minimum to the pre-calculated count for expected 10x load with some margin, since "average" spikes will sometimes be worse than average. Set a hard maximum from a genuine cost and risk ceiling, since a runaway metric-based scale-out with no ceiling can turn a traffic spike into a cost incident.
Worked example
Baseline traffic needs 4 instances to stay under the latency SLO with N+1 fault tolerance. The daily spike reaches 10x load for 30 minutes, and load testing showed 30 instances are needed to hold the SLO at that traffic level. A scheduled autoscale profile sets the minimum to 30 starting at 8:45 a.m. for a 9:00 a.m. spike, 15 minutes of lead time against an observed instance boot-to-healthy time of 4 to 6 minutes, and back to the baseline of 4 at 9:35 a.m., 5 minutes after the spike's observed end as a buffer against it running slightly long. On top of that scheduled floor, a queue-length-based rule adds up to 10 more instances (max cap 40) if request queue depth exceeds a threshold indicating the schedule under-provisioned for that particular day, with a 2-minute scale-out cooldown to react quickly to a bigger-than-expected spike and a 15-minute scale-in cooldown plus a 10-minute scale-in-protection grace period on newly added instances, so capacity is not removed within the same spike window just because one measurement interval looked calmer.
Trade-offs and pitfalls
Relying on metric-based scaling alone for a known, recurring spike reacts only after load has already started climbing, and can spend the first several minutes of the daily spike under-provisioned and breaching the SLO before capacity catches up, the main defect this design avoids. A health probe set to a shallow check that returns healthy before the application has actually finished warming up routes real traffic to instances that are not ready, causing exactly the tail-latency spikes autoscaling was supposed to prevent. And setting scale-in cooldown too short relative to how spiky load actually is within the 30-minute window creates thrashing that wastes both the compute cost of repeated boot cycles and the latency cost of repeated cold instances.
Unlock Full Question Bank
Get access to all Microsoft Azure Services and Architecture interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.