Why Teams Switch
Nobody migrates clouds for fun. The common triggers:
- Reliability frustration: Azure's outage track record in 2023-2025 pushed enterprise teams to evaluate alternatives
- Organizational mandate: the company standardized on AWS for everything else; the .NET team was the Azure holdout
- Pricing: AWS is often cheaper for the same workload, especially with Savings Plans and Graviton
- Service breadth: AWS has more services, more regions, and a faster feature release cadence
- Multi-cloud strategy: reducing single-vendor risk by running critical workloads on a second provider
Whatever the reason, the question is the same: how hard is this, and what breaks?
The Service Mapping
Most Azure services have direct AWS equivalents. The concepts translate; the APIs and configuration don't.
| Azure | AWS | Notes |
|---|---|---|
| App Service | ECS/Fargate, Lambda | Depends on workload characteristics |
| Azure Functions | Lambda | Same concept, different execution model |
| Azure SQL / SQL Server | Aurora PostgreSQL, RDS SQL Server | Aurora is cheaper; RDS gives you SQL Server if you need it |
| Cosmos DB | DynamoDB | Both NoSQL, but data model is very different |
| Azure Storage (Blobs) | S3 | Almost 1:1 mapping |
| Azure Service Bus | SQS + SNS, or EventBridge | No single equivalent. Decompose by pattern |
| Azure AD / Entra ID | Cognito (user auth), IAM (infra auth) | Different scope. Azure AD does more |
| Azure DevOps Pipelines | CodePipeline + CodeBuild | Or just use GitHub Actions for both |
| Azure Key Vault | Secrets Manager + Parameter Store | Two services instead of one, but cheaper |
| Azure Monitor | CloudWatch | Comparable, different query language |
| ARM Templates / Bicep | CloudFormation / CDK | CDK is the better developer experience |
| Azure Container Apps | ECS/Fargate | Similar simplicity level |
What Actually Changes
Your code: mostly nothing
If you're writing .NET, your application code is portable. HTTP endpoints, business logic, data access. It all works. What changes is the infrastructure wiring: how you connect to databases, how secrets are injected, how logs are shipped.
Your infrastructure: everything
ARM templates don't translate to CloudFormation. Azure RBAC doesn't map to IAM. VNet β VPC (similar concept, different implementation). This is the bulk of migration work.
Your deployment pipeline: rebuild it
Azure DevOps Pipelines β CodePipeline + CodeBuild, or (better) GitHub Actions deploying via CDK. The pipeline is usually rebuilt from scratch rather than translated.
Your team's mental model: shift required
Azure is organized around "resource groups" and a portal-centric workflow. AWS is organized around services with IAM tying them together. The AWS console is worse for exploration but better for automation. Teams that succeed on AWS think infrastructure-as-code first, console second.
Migration Strategies
Lift-and-shift (fastest, not cheapest long-term)
Move VMs and containers as-is. Azure VMs β EC2. Container Apps β ECS. Minimal code changes. You're running the same thing on different infrastructure. Do this to get off Azure quickly, then optimize.
Re-platform (balanced)
Move services one at a time, swapping Azure-specific services for AWS equivalents. App Service β Fargate. Azure SQL β Aurora. Service Bus β SQS. More work upfront, better cost and performance outcomes.
Re-architect (best outcome, most effort)
Redesign workloads to take advantage of AWS-native patterns. Decompose monoliths into Lambda functions. Replace Cosmos DB with DynamoDB single-table design. Implement event-driven patterns with EventBridge. Only do this for services that justify the investment.
The hybrid approach (recommended)
Most teams do all three simultaneously:
- Lift-and-shift the low-value, stable services (get them off Azure, worry about optimization later)
- Re-platform the active services that'll benefit from AWS-native equivalents
- Re-architect the 1-2 critical services where the investment pays off
Migration Order
Start with what's easiest and least risky:
- Static assets and CDN (Storage β S3 + CloudFront). Low risk, immediate win
- CI/CD pipeline (Azure DevOps β GitHub Actions + CDK). Enables everything else
- Stateless APIs (App Service β Fargate or Lambda). Portable, testable
- Data stores (the hard part). Plan carefully, data migration has the most risk
- Auth (Azure AD β Cognito or external IdP). Do this last, it touches everything
Common Mistakes
- Big-bang migration: trying to move everything at once over a weekend. Incremental is safer.
- Translating 1:1: forcing Azure patterns onto AWS instead of learning the AWS-native approach. Azure Service Bus with Topics β "find the one AWS service that does the same thing."
- Ignoring IAM: Azure RBAC is simpler (and less powerful). Teams that don't invest in understanding IAM end up with over-permissive policies.
- Underestimating networking: VPC design, subnets, NAT Gateways, VPC endpoints. Budget time for this.
- Not involving the team: migration works when engineers learn AWS, not when one person does it and everyone else continues thinking in Azure terms.
Further Reading
- AWS Migration Hub
- Azure to AWS service comparison: detailed compute options
- Azure to AWS reliability: uptime, redundancy, and the outage history
- .NET on AWS resources: service-by-service guides with C# code
Looking for hands-on help? View my modernization services β