Illustrative scenario. A representative engagement shape, not a client deployment. Design and rationale are real and reusable; the company is not. Aligned to the Microsoft Cloud Adoption Framework and Well-Architected Framework.
1. Scenario and constraints
A healthcare services company of roughly 200 staff runs a patient-facing scheduling application on-premises: IIS on Windows Server, SQL Server back end. Their datacenter lease expires and cannot be renewed.
| Constraint | Value | Drives |
|---|---|---|
| Hard deadline | 9 months to exit datacenter | Rehost over rearchitect |
| Data sensitivity | PHI must not traverse the public internet | Private Endpoints, Private Link origin |
| Availability target | 99.9% | Zone redundancy, not multi-region active-active |
| RPO | 15 minutes | Automated log backups |
| RTO | 4 hours | Warm secondary, not active-active |
| Compliance | HIPAA security assessment | Audit logging, encryption, access review |
| Team | 4 engineers, no prior Azure experience | Managed PaaS over self-operated |
| Licensing | Existing SQL Server + Windows Server with Software Assurance | Azure Hybrid Benefit |
The team constraint carries as much design weight as the compliance one. A platform nobody can operate is not a working platform.
2. Subscription and environment topology
Following the CAF subscription decision guide. The subscription is the boundary for policy, quota and billing, so it is the unit of separation, not resource groups.
| Management group | Subscription | Contains |
|---|---|---|
| Platform | sub-connectivity | Hub VNet, Azure Firewall, Private DNS zones, VPN gateway |
| Platform | sub-management | Log Analytics workspace, Automation, Backup vault |
| Workloads | sub-sched-prod | Production spoke, App Service, SQL MI |
| Workloads | sub-sched-nonprod | Dev and test spokes |
Four subscriptions, not the full enterprise-scale hierarchy. A 4-engineer team operating a nine-subscription landing zone spends its time on the landing zone. Dev and test share one subscription and separate by resource group and spoke; they have identical policy posture, so a subscription boundary between them buys nothing.
Environments: dev → test → prod, identical Bicep, different
parameter files. No environment is deployed by hand.
3. Naming convention
Per CAF resource naming and abbreviations.
<resource-type>-<workload>-<environment>-<region>-<instance>| Resource | Name |
|---|---|
| Resource group | rg-sched-prod-eus2-001 |
| App Service plan | asp-sched-prod-eus2-001 |
| Web app | app-sched-prod-eus2-001 |
| SQL Managed Instance | sqlmi-sched-prod-eus2-001 |
| Key Vault | kv-sched-prod-eus2-001 |
| Virtual network | vnet-sched-prod-eus2-001 |
| Storage account | stschedprodeus2001 |
Storage breaks the pattern because it is globally unique, lowercase alphanumeric only, 3–24 characters. Every convention meets a resource that will not accept it — decide the exception once and write it down, rather than letting each engineer improvise.
Naming is enforced by Azure Policy, not by review. A convention that depends on someone noticing does not survive an on-call deployment.
4. Network design
Hub and spoke. Region East US 2, paired secondary Central US for zone and region resilience.
| Scope | Range | Notes |
|---|---|---|
| Hub | 10.0.0.0/22 | sub-connectivity |
↳ AzureFirewallSubnet | 10.0.0.0/26 | Name is fixed by the platform |
↳ AzureBastionSubnet | 10.0.0.64/26 | /26 minimum |
↳ GatewaySubnet | 10.0.0.128/27 | ExpressRoute/VPN during migration |
↳ snet-shared | 10.0.1.0/24 | DNS resolvers, jump hosts |
| Prod spoke | 10.1.0.0/22 | sub-sched-prod |
↳ snet-app-integration | 10.1.0.0/24 | Delegated to Microsoft.Web/serverFarms |
↳ snet-privatelink | 10.1.1.0/24 | Private Endpoints |
↳ snet-sqlmi | 10.1.2.0/26 | Delegated to Microsoft.Sql/managedInstances |
| Non-prod spoke | 10.2.0.0/22 | Same layout |
| Reserved | 10.3.0.0/22 – 10.9.0.0/22 | Future workloads |
Contiguous /22 per spoke, allocated from a plan rather than on demand.
Overlapping ranges discovered later are the most expensive networking mistake
available, because the fix is a re-address under change control.
Egress is forced through Azure Firewall by user-defined route. One inspection and logging point, which is also the artifact the assessor asks for.
5. Design decisions
The constraint that shapes most of the table below is "PHI must not traverse the public internet." Traced end to end, the public segment stops at Front Door:
| Decision | Choice | Why | Rejected |
|---|---|---|---|
| Compute | App Service Premium v3 P1v3, zone-redundant | Existing IIS/.NET rehosts with no container work; no OS patching for a 4-person team | AKS — operational burden exceeds team capacity; VMs — patching and HA become the team's job |
| Database | SQL Managed Instance, Business Critical | Near-full T-SQL and SQL Agent compatibility, so the app moves in months not quarters; deploys inside the VNet with no public endpoint | Azure SQL Database — compatibility gaps cost schedule; SQL on VM — patching, backup and HA all become manual |
| Ingress | Front Door Premium + WAF | Managed OWASP ruleset, TLS termination, regional failover, and Private Link origin so the app is never publicly addressable | App Gateway alone — regional only, no failover story |
| PaaS connectivity | Private Endpoints + Private DNS zones | Satisfies "PHI does not traverse the public internet" literally | Service Endpoints — traffic stays on the Azure backbone but the resource keeps a public address |
| Secrets | Key Vault + managed identity | No credential exists to leak; nothing to rotate | Connection strings in app settings — the most common finding in an assessment |
| Governance | Azure Policy at management group, HIPAA/HITRUST initiative | Detective first, deny effects promoted once behaviour is understood | Deny-everything on day one — teams route around the platform |
| Logging | Central Log Analytics in sub-management, workload identities cannot delete | Evidence survives the incident it documents | Per-subscription workspaces — no correlation, no tamper resistance |
6. Resource inventory
| Service | SKU / tier | Purpose |
|---|---|---|
| App Service plan | Premium v3 P1v3, 3 zones | Web tier |
| SQL Managed Instance | Business Critical, 8 vCore, Gen5 | Application database |
| Front Door | Premium | Global ingress, WAF, Private Link origin |
| Azure Firewall | Standard | Egress inspection and logging |
| Key Vault | Standard, purge protection on | Secrets, certificates |
| Log Analytics | Pay-as-you-go → commitment tier | Diagnostics, audit retention |
| Backup vault | GRS | SQL long-term retention |
| Bastion | Standard | Break-glass administrative access |
7. Identity and access
- Microsoft Entra ID with SSO; on-prem AD synchronised during migration
- Privileged Identity Management for all owner and contributor roles — standing access is time-bound, not permanent
- Two break-glass accounts, excluded from Conditional Access, credentials sealed, sign-in alerted
- Application-to-database authentication via managed identity, no SQL logins
- Access reviews quarterly, exported as assessment evidence
8. Resilience: meeting the numbers
| Requirement | Mechanism | Result |
|---|---|---|
| RPO 15 min | SQL MI automated backups — transaction log every 5–10 min | ~10 min |
| RTO 4 hr, zone loss | Zone-redundant App Service + Business Critical replicas | Automatic, minutes |
| RTO 4 hr, region loss | Auto-failover group to Central US, warm App Service, Front Door origin priority | Within 4 hr |
| 99.9% availability | App Service 99.95% + SQL MI Business Critical zone-redundant 99.99% | Meets target with margin |
Failure modes tested, not assumed: zone loss, region failover drill, database point-in-time restore, and expiry of the Front Door certificate.
9. Cost: what dominates and what moves it
SQL Managed Instance Business Critical is the largest line item by a wide margin. Optimise it before anything else; tuning App Service while SQL runs unreserved is effort in the wrong place.
| Lever | Mechanism | Notes |
|---|---|---|
| Azure Hybrid Benefit | Apply existing SQL Server and Windows Server licences with Software Assurance | The single largest lever in any migration from owned infrastructure, and routinely missed because the licences sit with procurement rather than engineering |
| Reservations / savings plan | 1- or 3-year commitment on steady-state compute | Apply after the baseline is measured, not at design time |
| Non-prod sizing | General Purpose instead of Business Critical; scheduled shutdown outside working hours | Non-prod has no availability requirement — matching it to prod is spending for nothing |
| Log retention tiering | Interactive retention for the operational window, archive beyond it | Retention obligations run years; interactive retention priced for years is a large avoidable cost |
| Right-sizing | Review against real telemetry after the first full cycle | Pre-optimising a workload nobody has observed produces the wrong answer confidently |
Cost is a design output, not a monthly surprise: budgets and anomaly alerts are provisioned by the same templates that create the resources.
10. Infrastructure as code
Bicep, built on Azure Verified Modules.
Why Bicep here. No state file to store, lock or corrupt — a real consideration for a team new to the platform. New Azure resource types are supported on release rather than waiting on a provider. The tradeoff is honest: Terraform is the better choice for a multi-cloud estate or an established module ecosystem, and we would recommend it in that case.
Pipeline. GitHub Actions authenticating by OpenID Connect federation — no service principal secret is stored anywhere.
pull request → bicep build + lint → what-if against target → plan on PR
merge to main → deploy dev → smoke tests
deploy test → integration tests
deploy prod → approval gateThe what-if output is posted to the pull request, so the diff is reviewed
before it is applied rather than discovered afterwards.
What this buys. Environment parity by construction — dev, test and prod differ only by parameter file, so "works in test" carries meaning. Rebuild from source is a routine operation rather than a recovery plan. And every infrastructure change arrives with an author, a reviewer and a reason attached, which is most of what an assessor wants from change management.
11. What changes if
| If | Then |
|---|---|
| Team has Kubernetes experience | AKS becomes viable; better density and cost at scale, at the price of an operational burden that must be staffed |
| RTO tightens to 1 hour | Active-active across regions; roughly doubles the platform bill |
| No existing licences | Azure Hybrid Benefit disappears; re-evaluate Azure SQL Database against the compatibility work |
| Data residency is mandated | Region pairing becomes a constraint rather than a choice; verify the paired region satisfies it |
| Budget is the binding constraint | General Purpose SQL MI, single region, and an explicitly agreed lower RTO — written down and signed off, not discovered during an incident |
| Migration deadline extends | Rearchitecting the data layer becomes worth evaluating; under nine months it is not |
12. What we deliver
- This topology as reviewed Bicep, parameterised to your constraints
- A decision record for every deviation from this baseline, so the reasoning outlives the engagement
- Runbooks for the parts that need a human: break-glass access, failover drill, policy promotion, retention review
- A cost baseline with budgets and anomaly alerts deployed alongside the infrastructure