Sapior LogoSapior

Coming from AWS? Here’s the mental model that finally made Azure click for me

Azure stopped feeling like a foreign cloud the day I stopped translating services one-to-one and started seeing tenants, subscriptions, resource groups, and Entra ID as the product surface.

I came from AWS, and for months Azure felt like somebody had rebuilt the cloud console from a database diagram. There were tenants, subscriptions, resource groups, Entra ID, management groups, and an endless set of portal blades. I kept asking what the Azure equivalent of X was. That was the mistake.

Azure didn’t click until I stopped treating it as translated AWS and started treating it as a different product with a different thesis: Azure is an identity-first, resource-plane product. AWS is a service-first, account-scoped product.

That reframe changed everything.

The core mental model

In AWS, you mostly live inside an account, a region, and a service namespace. You assume an IAM role, deploy into a VPC, and use ARNs that encode account, region, service, and resource. It’s straightforward once you know the grammar.

Azure’s grammar is different. The hierarchy is:

Tenant (Entra ID) > Management groups > Subscriptions > Resource groups > Resources

Tenant: the organizational identity boundary. It’s where users, groups, and service principals live. In AWS, the closest parallel is an organization plus its IAM identity source, but it sits above any subscription.

Management groups: optional policy and governance folders for subscriptions. They map loosely to AWS Organizations OUs, but they’re not required for small workloads.

Subscriptions: the trust, billing, and policy boundary. This is closer to an AWS account, but not exactly, because identity is not scoped to a subscription the way IAM users are scoped to an account.

Resource groups: the lifecycle boundary. Every resource must live in one. They map most closely to a CloudFormation stack’s resource collection, but they’re also used for RBAC, policy, cost, and operations.

Resources: the actual services and objects.

Once I internalized that hierarchy, Azure became legible. I stopped looking for a VPC account and started asking: which subscription? which resource group? which identity?

Identity is not an account afterthought

AWS taught me that IAM is powerful but often account-scoped. You can use IAM Identity Center and Organizations to make it feel more unified, but the core IAM model is per account.

Azure inverts this. Entra ID, formerly Azure Active Directory, is the identity provider and identity perimeter. Your subscription trusts an Entra tenant. A user or service principal from that tenant can be granted access to resources across many subscriptions without creating a new identity in each one. That felt weird until I realized it’s like AWS IAM Identity Center made mandatory, with the tenant as the single directory.

Practical consequences:

Don’t confuse Entra ID roles, which are directory-level such as Global Administrator, with Azure RBAC roles, which are subscription or resource-level such as Contributor, Owner, and Reader.

Managed identities replace long-lived service account keys for most Azure services. Treat them like an AWS instance profile, but available for more than just EC2.

Service principals are Azure’s counterpart to IAM users or roles for automation. You grant them roles at subscription or resource group scope.

Microsoft’s [Entra ID documentation](https://learn.microsoft.com/en-us/entra/fundamentals/what-is-entra-id) describes the tenant as an organization’s dedicated instance of the directory. That’s the right way to think about it: the tenant is the directory; subscriptions are the workload boundaries that trust it.

Resource groups are the unlock

For me, the most important mental shift was resource groups. In AWS, a resource group is a tag-based view or something optional. In Azure, every resource must be in a resource group, and the group carries lifecycle, access, policy, and cost metadata. It’s less like a folder and more like a deployment unit or a CloudFormation stack.

A resource group should contain resources that share the same lifecycle. If you delete the group, you delete everything inside it. If you apply policy to the group, everything inside inherits it. If you grant a developer Contributor on a group, they can manage those resources without subscription-wide access.

This made Azure feel surprisingly clean for application teams. Instead of granting many per-service IAM permissions, you can grant access at the resource group scope for an entire app: its compute, storage, network, and secrets.

Networking feels different because the defaults are different

Coming from AWS, I expected a VNet to behave like a VPC. It does at a high level, but the defaults are not the same.

Key differences:

Azure VMs do not get a public IP by default. You must attach a public IP resource if you need inbound internet.

Network security groups are associated with subnets or NICs, not with a VPC-wide security group concept like AWS SGs. They also have an explicit allow/deny rule set, unlike AWS security groups’ allow-only model.

Private connectivity to PaaS services is via Private Endpoints, which create a NIC in your VNet and map the service to a private IP. It’s similar to AWS PrivateLink, but it’s a core pattern for almost every managed service, not an occasional add-on.

Peering is available, but cross-subscription and cross-region concerns require more attention than VPC peering in many cases.

The [Azure Architecture Center networking decision guide](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/azure-networking-architecture) recommends a hub-and-spoke topology for central connectivity, security, and governance. That pattern is common in AWS too, but Azure’s subscriptions and VNet peering make the topology feel more explicit.

Compute and platform services map by shape, not by exact feature

If you chase exact Azure equivalents for AWS services, you’ll get stuck. Better to map by shape and control plane.

| AWS | Azure | Notes |

|-----|-------|-------|

| EC2 | Virtual Machines | Similar, but VMSS handles scale-out; no default public IP |

| Lambda | Azure Functions | Event-driven but packaging and triggers differ |

| EKS | Azure Kubernetes Service (AKS) | Managed control plane; Azure-specific CNI and identity |

| S3 | Azure Blob Storage | Storage accounts and containers instead of buckets |

| EFS | Azure Files | SMB/NFS file shares |

| IAM roles | Entra roles + Azure RBAC roles + managed identities | Directory roles vs resource roles |

| CloudFormation | ARM templates / Bicep | Bicep is the far more pleasant modern path |

| VPC | Virtual Network | Similar, different security defaults |

| PrivateLink | Private Endpoints | Core connectivity pattern for PaaS |

| Organizations SCPs | Azure Policy at management group or subscription | Policy and governance |

This table is a starting point, not a finish line. The mental model is more important than the exact match.

The ARM control plane is the actual product

The thing that made Azure click for me was this: Azure Resource Manager is the API. Every resource, whether it’s a VM, a SQL database, or a private endpoint, is represented in the same resource provider model. You write ARM templates or Bicep against that model. The Azure CLI and PowerShell cmdlets use it. The portal uses it.

That consistency is different from AWS, where CloudFormation, the console, and the CLI sometimes feel like different generations of API. In Azure, the control plane is unusually uniform. Bicep is worth learning immediately. It removes most of the JSON ceremony from ARM templates and gives you a clean, declarative language that feels closer to Terraform than to raw CloudFormation YAML.

The mental model that finally made it stick

When I see an Azure architecture now, I don’t try to translate it into AWS. I read it in this order:

1. Which Entra tenant owns identity and trust?

2. Which subscription is the billing and policy boundary?

3. Which resource group owns the workload lifecycle?

4. Which resources inside that group make up the app?

5. Which roles and identities can touch those resources?

6. Which network paths and private endpoints connect them?

That order is the opposite of how I used to read AWS, where I started with services and then asked about accounts and roles later. For Azure, the hierarchy is the product.

Practical tips for AWS engineers

Stop comparing services one-to-one. Start with the resource hierarchy.

Learn Bicep early. It makes the ARM control plane feel approachable.

Treat resource groups as deployable units. Don’t create one per resource, but don’t create one giant group either.

Use management groups when you need governance across many subscriptions. Skip them for small environments.

Design networking around private endpoints and NSGs from the start, because the defaults won’t save you the way AWS security groups often do.

Grant RBAC at resource group scope for app teams. It matches the lifecycle boundary.

Use managed identities instead of service principal secrets whenever possible.

The bottom line

Azure stopped feeling confusing when I realized it isn’t AWS with different names. It’s a different cloud with a consistent resource hierarchy and an identity-first control plane. Once you stop translating and start reading the hierarchy, the service names begin to make sense.

That shift took me longer than I’d like to admit. But after it happened, Azure became far more predictable to deploy, govern, and operate.

Coming from AWS? The Mental Model That Makes Azure Click