A senior engineer's guide to running .NET and ASP.NET on AWS, usually off Azure or on-prem IIS. The decision that defines the project: cross-platform .NET 8/9 goes Linux-native on App Runner, ECS Fargate, or Lambda; legacy .NET Framework runs in Windows containers or on EC2 until you port it — and Porting Assistant for .NET tells you how far that port actually is. This page walks the targets honestly, the AWS Toolkit for .NET, RDS for SQL Server vs Aurora + Babelfish, the IIS→ALB translation, the cutover, and how the AWS Optimization & Licensing Assessment (OLA) plus MAP make a vetted partner run it at low-to-no cost.
People search "migrate .net to aws" or "asp.net on aws" for a handful of reasons: an acquirer or parent company standardized on AWS, an Azure EA renewal made the all-in commit look worse than a clean AWS landing zone, the team wants AWS's breadth (Bedrock, the maturity of ECS/EKS, the data stack), or an on-prem Windows estate on aging IIS servers is overdue for the cloud. The trigger varies; the engineering decision tree does not.
Before any AWS service enters the conversation, classify the application by runtime, because that single fact changes the cost, the target, and the timeline more than anything else. Modern .NET — .NET Core 3.1, and the unified .NET 5, 6, 7, 8, and 9 — is cross-platform and runs natively on Linux. That means cheap Linux compute, small containers, and first-class support on every AWS serverless and container runtime. Legacy .NET Framework (4.8 and earlier) is Windows-only by design: it runs on AWS, but only on Windows containers or EC2 Windows instances, which carry a Windows Server license and cost more. A surprising number of "ASP.NET" estates are a mix — some services already on .NET 8, others stuck on Framework 4.7.2 because of a dependency nobody has had time to replace.
So the real decision tree is: (1) rehost as-is — Framework on EC2/Windows or modern .NET on Linux containers, fastest, keeps the Windows bill where Framework is involved; (2) replatform — containerize and move to a managed runtime (App Runner / ECS Fargate / Lambda), the common sweet spot; or (3) refactor/port — move .NET Framework to cross-platform .NET so it can run on Linux, shedding the Windows license entirely. In AWS's 7 Rs language that is Rehost, Replatform, and Refactor respectively; most teams rehost or replatform first to get onto AWS, then port the high-value Framework apps to Linux .NET to capture the savings.
The two early architectural decisions that matter as much as the runtime are the landing zone — a multi-account AWS Organizations structure (management, security/log-archive, shared-services, per-environment workload accounts), a network baseline, guardrails, and centralized logging, which is what the MAP "Mobilize" phase funds and the thing teams most regret skipping — and the data tier, which for .NET almost always means SQL Server and is its own sub-project (Section IV). The rest of this page is the honest detail on each, plus the tooling (Porting Assistant, the AWS Toolkit) that makes the port measurable instead of a guess.
For cross-platform .NET 8/9, AWS gives you three good homes. Choosing between them is mostly about how much of the platform you want to own versus hand to AWS, and what the traffic shape looks like. None of these is wrong; they sit on a control-versus-convenience curve.
A note before the options: all three assume your .NET is (or will be) cross-platform and containerized or packaged. If it is still .NET Framework, you are choosing from the Windows column instead (Section III), and these become the destination after a port. The AWS Toolkit for .NET — covered in Section V — publishes to all three from Visual Studio or the CLI.
For a single ASP.NET Core web app or API, App Runner is the most like-for-like target if you are coming from Azure App Service or a Heroku-style PaaS. You hand it a container image (from ECR) or point it at source, and it gives you a managed, autoscaling, HTTPS endpoint with zero infrastructure to run — it provisions the load balancer, TLS, and scaling for you. It is the fastest path to "my ASP.NET app is live on AWS."
Verdict: ideal for straightforward web apps and APIs that want managed simplicity. The tradeoff is less control — limited networking knobs and no sidecars. When you outgrow it, ECS Fargate is the next step up, and the container image you built moves across unchanged.
ECS on Fargate is the workhorse for most .NET migrations with more than one service, sidecars, or finer networking control. You define task definitions, run them serverlessly (no EC2 to patch), front them with an Application Load Balancer, and get full control over VPC placement, security groups, autoscaling policies, and service discovery. It runs both Linux containers (modern .NET) and — importantly — Windows containers for .NET Framework, which makes it the bridge runtime during a phased port.
Verdict: the safe default for a multi-service ASP.NET estate. More wiring than App Runner, far less than running Kubernetes. If you are already invested in Kubernetes, EKS is the equivalent target and the manifests move over, but ECS is simpler to operate for a .NET shop without existing k8s expertise.
Lambda runs .NET as managed functions — natively for modern .NET via managed runtimes, and you can package .NET as a container image up to 10 GB if you need a custom base. It shines for event-driven work (S3/SQS/EventBridge/API Gateway triggers), bursty or spiky traffic where you do not want to pay for idle compute, and background jobs. ASP.NET Core APIs can run on Lambda behind API Gateway via the Lambda ASP.NET Core hosting shim, which lets you lift a Minimal API or controller app with modest change.
Verdict: excellent for new event-driven pieces and spiky APIs; cold starts and the 15-minute execution ceiling make it a poor fit for long-running or latency-critical request paths. .NET Framework cannot run on Lambda at all — Lambda is Linux, so this option is modern-.NET-only and another reason the port pays off.
Single web app that wants zero ops → App Runner. A real multi-service estate that wants control without Kubernetes → ECS Fargate (and the only managed home for Windows-container .NET Framework). Event-driven, bursty, or background work → Lambda. Already running Kubernetes → EKS. You can mix them in one estate, and the AWS Toolkit deploys to all of them.
Most real .NET migrations carry at least one .NET Framework 4.x application that cannot move to Linux without work. Pretending otherwise is how projects slip. There are three honest options for Framework code, and a tool that tells you which one each app deserves.
Option one, rehost to EC2 Windows: lift the IIS/Windows VM essentially as-is using AWS Application Migration Service (MGN), agent-based block-level replication so you cut over with minutes of downtime. Fastest, lowest-risk, requires no code change — but you carry the Windows Server license (and any SQL Server license) into AWS unchanged. Use it for apps you must move now and cannot touch yet.
Option two, Windows containers on ECS/EKS: containerize the Framework app into a Windows container and run it on ECS (or EKS) with Windows nodes. You get container packaging, CI/CD, and a path toward the rest of your AWS-native tooling without porting the code, while still paying Windows licensing on the Windows capacity. It is a useful halfway house — modernize the deployment model first, port to Linux later.
Option three, port to cross-platform .NET, then run it like any modern app on App Runner / ECS Fargate / Lambda (Section II). This is the only option that removes the Windows Server license entirely. The barrier is knowing how big the port is — which is exactly what Porting Assistant for .NET answers. It is a free AWS tool that scans your solution, inventories every NuGet dependency and API call, flags what is and is not compatible with cross-platform .NET, scores the porting effort per project, and can apply mechanical fixes. You run it before committing so the port is a measured number, not a leap of faith. Apps heavy on Framework-only surface area — classic WCF, WebForms, System.Web, legacy GAC dependencies — score as expensive and are often the ones you rehost to EC2/Windows containers first and port later, if ever.
ASP.NET WebForms has no cross-platform equivalent — porting effectively means re-writing the UI tier (often to Blazor or a SPA + ASP.NET Core API), so these usually rehost to Windows first. Classic WCF services need CoreWCF or a move to gRPC/HTTP. WinForms/WPF desktop apps are out of scope for server migration. Porting Assistant quantifies all of this up front — let the score, not optimism, decide which Framework apps get ported versus parked on Windows.
A .NET application almost always sits on SQL Server, so the migration is really two projects: the app tier above and the data tier here. You have two main destinations, and the choice turns on whether you want to keep — or kill — the SQL Server license bill. This is a deep topic with its own dedicated guide; the summary below is enough to plan around, and the link carries the detail.
The low-risk path is Amazon RDS for SQL Server: same engine, managed by AWS, license-included or BYOL, minimal application change because your T-SQL and EF Core/EF6 data layer keep working as-is. You move the data with AWS Database Migration Service (DMS) — full load then change-data-capture (CDC) — so the cutover is a short maintenance window, not a weekend. You keep paying SQL Server licensing, but right-sizing on RDS already trims the bill.
The cost-saving path is Aurora PostgreSQL with Babelfish: a compatibility layer that speaks SQL Server's TDS wire protocol and a large subset of T-SQL, so many ASP.NET apps keep connecting on port 1433 with little or no change while the SQL Server license disappears entirely. You start with the free Babelfish Compass tool to measure how much of your T-SQL is covered, use the AWS Schema Conversion Tool (SCT) for the remainder, and DMS for the data. The honest caveat: Babelfish does not cover everything (SQL Agent jobs, SSIS, CLR, linked servers, and some advanced T-SQL need re-architecting), so Compass is your go/no-go number per database.
For a .NET migration specifically, the most common pattern is to rehost the data to RDS for SQL Server alongside the app move to get onto AWS fast, then evaluate Babelfish as a follow-on to cut licensing once the app is stable. EF Core abstracts the database provider, which makes the eventual PostgreSQL move more tractable than a raw-ADO.NET app — but stored procedures and inline T-SQL are where the real conversion effort lives. The full decision — RDS vs Aurora + Babelfish vs SQL Server on EC2, the SCT/DMS workflow, Always On / HA, and the OLA licensing analysis in depth — is covered in the dedicated SQL Server to AWS guide.
A .NET team does not want to learn a whole new console to ship. AWS's .NET tooling is good enough in 2026 that most of the migration happens from inside Visual Studio, the CLI, or your existing pipeline — and the IIS concepts you rely on have clean AWS equivalents.
The AWS Toolkit for .NET is the developer on-ramp. The AWS Toolkit for Visual Studio adds AWS Explorer, credential management, and one-click publish to App Runner, ECS Fargate, Elastic Beanstalk, and Lambda directly from the IDE. The AWS Deploy Tool for .NET (the `dotnet aws` CLI command) inspects your project, recommends a target (App Runner vs ECS vs Lambda) based on what the app looks like, and generates the deployment — it is the fastest way to get a first deploy working and to learn the right shape. The AWS SDK for .NET swaps in for Azure SDK calls (Blob → S3, Service Bus → SQS/SNS, Key Vault → Secrets Manager/SSM), and the AWS Lambda templates for .NET scaffold function and ASP.NET-on-Lambda projects.
For infrastructure as code, a .NET shop has a native-feeling option: AWS CDK supports C#, so you can define the landing zone and per-service resources in the same language as the app. Teams that prefer cloud-agnostic IaC use Terraform instead. Either way, the deliverable is a peer-reviewed, version-controlled definition of the AWS estate that a pipeline applies — not console click-ops. Azure DevOps Pipelines (a very common .NET CI/CD home) map to CodePipeline/CodeBuild or GitHub Actions with AWS OIDC, and that is a parallel workstream, not a cutover blocker.
On the runtime translation, the IIS concepts map cleanly. An IIS site/binding becomes an Application Load Balancer (ALB) listener and target group fronting your App Runner service, ECS tasks, or EC2 instances; host headers become ALB host-based routing rules; SSL termination at IIS moves to the ALB with an ACM certificate (free, auto-renewing). IIS application pools and worker processes map to container task sizing and the Kestrel web server that ASP.NET Core runs by default — you generally drop the reverse-proxy-to-IIS pattern and let the ALB talk to Kestrel directly. Windows Authentication / integrated auth, if you rely on it, is the fiddly part: it maps to ALB OIDC or Amazon Cognito for app sign-in, with the corporate directory federated (Active Directory via AWS Directory Service or IAM Identity Center) — inventory where you use integrated auth early, because it is the IIS feature with the least direct equivalent.
A good .NET migration is boring. You move in waves, run AWS in parallel for the data tier, and keep a tested rollback for every wave. The "big-bang weekend" works until it doesn't — then you are debugging Windows containers, identity, and SQL Server replication at once under a downtime clock. Here is the shape of a typical 8–20 week .NET migration.
Waves isolate failure: each is small enough to validate and roll back independently, and the order is deliberate — landing zone first, stateless app tier next, SQL Server last.
Inventory every application and classify it by runtime (modern .NET vs .NET Framework) and by the 7 Rs. Run Porting Assistant for .NET across the solutions to score the port effort, and run the OLA to quantify the Windows Server + SQL Server licensing you are paying and what each path saves. The output is a target architecture, a costed business case, and a per-app verdict (rehost on Windows / containerize / port to Linux). This is the MAP "Assess" deliverable and AWS typically funds it — you finish with a plan and a number, not an invoice.
Build the landing zone: AWS Organizations, accounts, network baseline (VPCs, Transit Gateway, Direct Connect or VPN back to the source for the parallel-run window), guardrails, centralized logging, and identity (Active Directory federated to IAM Identity Center; Cognito for customer-facing auth). Stand up ECR, the CI/CD pipeline, and the CDK/Terraform modules. Run a pilot — migrate one representative, low-risk .NET service end to end to prove the toolchain (Deploy Tool, MGN, DMS) and the runbook. This phase is also MAP-funded.
Move the stateless app tier first because it is reversible. Modern .NET services containerize and deploy to App Runner/ECS Fargate; .NET Framework apps either rehost to EC2 Windows via MGN or run as Windows containers on ECS, per the Phase 0 verdict. Run AWS in parallel behind a weighted Route 53 DNS record so you can shift traffic 5% → 25% → 100% and roll back instantly by reverting the weight. Ported apps get full regression testing here, because behavior on Linux Kestrel can differ from Framework-on-IIS in subtle ways (case-sensitive paths, culture/encoding defaults, file-system assumptions).
The database cuts over last and most carefully. Stand up the target (RDS for SQL Server, or Aurora + Babelfish), seed a full load, then run DMS CDC to keep it continuously in sync with the live source, validated with DMS data-validation. The cutover is a short maintenance window: stop writes to the source, let CDC drain the last changes, flip the connection string, verify, open writes on AWS. Keep the source database read-only as a rollback target for a defined window. For the Babelfish path, this is where the SCT-converted objects and the non-covered re-architecture (Agent jobs, SSIS) get validated end to end.
Run the full test suite against AWS, watch CloudWatch and cost for a billing cycle, right-size based on real usage, then decommission the source once you are confident — which also stops the old bill (and, for ported apps, ends the Windows/SQL license line). This is where MAP "Modernize" credits often fund the follow-on work — porting the remaining Framework apps off Windows, or moving from RDS for SQL Server to Babelfish. Do not skip decommission: a half-shut-down on-prem or Azure estate is pure cost.
Every wave has a tested rollback: app tiers roll back by reverting the Route 53 weight; SQL Server rolls back by keeping the source read-only and re-pointing the connection string. Ported .NET apps keep their Windows-container/EC2 version deployable as a fallback until the Linux version has soaked. A migration without a rollback plan is a bet, not a plan — the partner writes and rehearses the runbook before the window, not during it.
For a .NET migration, the financial story is not just "AWS is cheaper compute." It is "moving .NET Framework on Windows to cross-platform .NET on Linux can delete the Windows Server license line entirely — and AWS will pay you to figure out by how much." This is the angle most .NET teams underprice.
Every .NET Framework app on EC2 Windows or Windows containers carries a Windows Server license on top of the compute, and if it talks to SQL Server, a SQL Server license too. Porting that app to modern .NET lets it run on Linux containers — no Windows Server license, smaller images, cheaper compute, and often a path to dropping SQL Server for Aurora + Babelfish on top. The savings are real and recurring, but they only land for apps that are actually ported, which is why the Porting Assistant score (Section III) drives the business case.
AWS funds the analysis through the Optimization & Licensing Assessment (OLA) — an AWS-funded engagement that inventories your real Windows and SQL Server core usage and Software Assurance position, then models BYOL vs license-included vs porting-to-Linux so the decision is data-driven rather than a guess. It pairs with the Migration Acceleration Program (MAP), which runs in three phases — Assess (TCO/readiness, often fully funded), Mobilize (landing zone + pilot, funded), and Migrate & Modernize (production cutover, where AWS credits a meaningful share of the cost). The partner is paid through MAP and AWS engagement funding, and credits scale with migration size. Honest framing: MAP funding applies to qualifying migrations — typically tied to a committed level of post-migration AWS spend, not a blank check — but for a real .NET estate moving to AWS, the assessment is commonly free and a large share of the migration cost is covered.
This is where CloudRoute fits. We do not run migrations — we route you to a vetted, MAP- and OLA-eligible AWS partner who does, matched to your stack (.NET Framework vs modern .NET, SQL Server, the size of the Windows estate), region, and timeline. You get a partner who has run the Porting Assistant pass and the IIS→ALB translation before, the migration is largely MAP-funded, the OLA quantifies your licensing win, and CloudRoute is paid by the partner — so the routing costs you nothing. The same MAP/credits machinery underpins our AWS credits work and the POC-funding path, and the partner's landing zone is exactly the kind covered in AWS landing zone. For the full done-for-you picture — assessment, landing zone, cutover, and the funding mechanics — the migration persona page walks through how an engagement runs end to end.
These are the items that do not show up in a target-comparison table but reliably cost a .NET team a day each. A partner who has done .NET→AWS before front-loads all of them; a first-time team discovers them one incident at a time.
The single decision that defines the project, condensed. "Modern .NET" means .NET Core 3.1 and the unified .NET 5–9 (cross-platform, Linux-capable); ".NET Framework" means 4.x and earlier (Windows-only). The funding and license columns are why the port is worth scoping.
| Dimension | .NET Framework (4.x) | Modern .NET (8 / 9) |
|---|---|---|
| OS | Windows only | Linux or Windows (Linux is the cheap default) |
| Primary AWS targets | EC2 Windows · Windows containers on ECS/EKS | App Runner · ECS Fargate · Lambda · EKS |
| Runs on Lambda? | No (Lambda is Linux) | Yes (managed runtime or container image) |
| Windows Server license | Required (carried into AWS) | None on Linux — license eliminated |
| Migration move (7 Rs) | Rehost (MGN) or containerize-as-Windows now | Replatform to managed runtime; refactor selectively |
| Bridge / assessment tool | Porting Assistant for .NET scores the port | AWS Deploy Tool recommends the target |
| Typical effort | Low to rehost; high to port (WebForms/WCF expensive) | Low — containerize and publish |
| Funding angle | OLA quantifies the Windows/SQL license you shed by porting | MAP funds the replatform; lowest run cost |
Situation: Datacenter lease ending forced the move; the board wanted off Windows licensing where possible. The estate was mixed — modern .NET microservices alongside a core policy-admin app on .NET Framework 4.8 with heavy WebForms screens and a pile of SQL Agent jobs and SSIS. No one in-house had run an AWS migration, the platform lead was at capacity, and nobody knew which Framework apps were worth porting versus rehosting.
What CloudRoute did: Routed within 24 hours to a MAP- and OLA-eligible partner with a .NET + SQL Server track record. MAP Assess (AWS-funded) ran Porting Assistant across all 14 solutions and the OLA across the Windows/SQL estate in 2 weeks — verdict: replatform the 5 modern services and 4 of the Framework apps to Linux .NET on ECS Fargate, port 1 mid-complexity Framework API, and rehost the WebForms policy-admin app to EC2 Windows (port deferred — WebForms re-write out of scope for phase one). Mobilize built a multi-account landing zone with AD federated to IAM Identity Center and a Direct Connect circuit. App tier moved in waves behind Route 53 weighting; IIS sites became ALB listeners + Kestrel; SQL Server went to RDS for SQL Server via DMS CDC, with Babelfish flagged as a phase-two licensing follow-on.
Outcome: Full cutover in 15 weeks, zero unplanned downtime (database windows under 10 minutes). The OLA-driven port to Linux .NET removed Windows Server licensing on 9 of 14 apps; MAP funded Assess + Mobilize and credited ~45% of the migrate-and-modernize cost against a post-migration AWS commitment. On-prem decommissioned in week 17, ahead of the lease end. CloudRoute was paid by the partner — the customer paid $0 for the routing.
timeline: 15 weeks · downtime: <10 min/db · Windows license removed on 9/14 apps · MAP-funded: ~45% of migrate cost · routing cost to customer: $0
CloudRoute routes you to a MAP- and OLA-eligible AWS partner matched to your stack — .NET Framework or modern .NET, SQL Server, the size of your Windows estate. Assessment is often free; the migration is largely MAP-funded on qualifying workloads, and the OLA quantifies your Windows-license savings. Customer pays $0 for the routing — no procurement, no discovery theater.