Deploying ASP.NET Core on Azure: App Service vs Container Apps vs AKS
Azure gives you at least five ways to run an ASP.NET Core application, and choosing the wrong one is expensive in both directions: over-engineered Kubernetes clusters for a simple web app, or a platform that can't handle the background processing and scaling your product eventually needs. In practice the choice for most .NET teams comes down to three services: Azure App Service, Azure Container Apps and Azure Kubernetes Service (AKS). Here's how they compare and how I choose between them for client projects.
The short answer
- App Service: the default for web apps and APIs. Least operational work, mature, predictable.
- Container Apps: the default for containerised systems with several services, background workers or event-driven scaling, including scale to zero.
- AKS: for organisations that need full Kubernetes control and have (or will hire) the platform team to run it.
Azure App Service
App Service is a fully managed platform for web applications. You deploy code (or a container), and Azure handles the operating system, patching, load balancing and TLS certificates.
Strengths
- Fastest path to production: deploy from Visual Studio, GitHub Actions or Azure DevOps in minutes.
- Deployment slots for zero-downtime releases: deploy to staging, warm it up, swap.
- Built-in custom domains, free managed certificates, authentication (Easy Auth), autoscale rules and VNet integration.
- Linux plans are cheap and run modern .NET very efficiently.
Limitations
- You pay for the plan even when traffic is zero; there's no scale to zero on dedicated plans.
- Scaling is based on CPU, memory or schedules rather than queue length or events.
- Less suited to many small services or long-running background workers (WebJobs exist, but are limited).
Choose it for: company websites, line-of-business applications, a single API plus a front end, and SaaS products in their first years.
Azure Container Apps
Container Apps runs containers on a managed Kubernetes-based platform without exposing Kubernetes itself. You get revisions, ingress, autoscaling with KEDA and optional Dapr integration, while Microsoft runs the cluster.
Strengths
- Scale on HTTP traffic, queue length (Service Bus, Storage queues), Kafka, cron and more, including scaling to zero, so idle workers cost nothing on the consumption plan.
- Natural home for a modular monolith plus a few satellite services: an API, a worker, a scheduled job, all in one environment with internal networking.
- Revisions with traffic splitting for blue/green and canary releases.
- Container Apps Jobs for batch and scheduled workloads.
- Works very well with .NET Aspire, which can generate the deployment for you with the Azure Developer CLI (
azd up).
Limitations
- You need to build and manage container images and a registry.
- Cold starts when scaling from zero (keep a minimum replica for latency-sensitive APIs).
- Less low-level control than raw Kubernetes: no custom operators or arbitrary cluster add-ons.
Choose it for: event-driven systems, products with background processing, several cooperating services, and workloads with very spiky traffic.
Azure Kubernetes Service
AKS gives you a managed Kubernetes control plane; everything else (node pools, ingress controllers, networking, policies, upgrades, observability) is yours to design and operate.
Strengths
- Full Kubernetes API: Helm charts, operators, service meshes, GitOps with Flux or Argo CD.
- Fine-grained control over networking, node types (GPU, spot, ARM) and multi-tenancy.
- Portable skills and manifests across clouds.
Limitations
- Real operational cost: cluster upgrades, security patching, capacity planning and on-call. Budget for platform engineering time, not just compute.
- Easy to over-engineer. Many teams run a handful of services on AKS that would be cheaper and simpler on Container Apps.
Choose it for: large platforms with many teams and services, strict networking or compliance requirements, or an existing Kubernetes investment.
Side-by-side comparison
| App Service | Container Apps | AKS | |
|---|---|---|---|
| Unit of deployment | Code or container | Container | Container (Kubernetes manifests) |
| Ops effort | Very low | Low | High |
| Scale to zero | No (dedicated plans) | Yes | Possible with KEDA, you manage it |
| Event-driven scaling | Limited | Built in (KEDA) | Yes, you configure it |
| Background workers | WebJobs | Apps and Jobs | Anything |
| Zero-downtime releases | Deployment slots | Revisions and traffic splitting | Rolling updates, your tooling |
| Best for | Web apps and APIs | Microservices, workers, event-driven | Large platforms, full control |
Preparing an ASP.NET Core app for any of them
Whichever platform you choose, the same practices make the app cloud-ready:
Containerise without a Dockerfile
The .NET SDK can build an optimised container image directly:
dotnet publish -c Release /t:PublishContainer -p:ContainerRepository=shop-api
Add health checks
builder.Services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
app.MapHealthChecks("/health/live", new() { Predicate = _ => false }); // process is up
app.MapHealthChecks("/health/ready"); // dependencies are reachable
Point the platform's liveness and readiness probes (or App Service health check) at these endpoints so unhealthy instances are replaced automatically.
Use managed identity instead of secrets
builder.Configuration.AddAzureKeyVault(
new Uri(builder.Configuration["KeyVault:Uri"]!),
new DefaultAzureCredential());
With a managed identity, the app authenticates to Key Vault, Azure SQL, Storage and Service Bus without any password in configuration.
Observability from day one
Add OpenTelemetry with the Azure Monitor exporter (or the Aspire service defaults) to get distributed traces, metrics and logs in Application Insights. When something breaks at 2 am, this is what tells you where.
Automate deployments
Use GitHub Actions or Azure DevOps with infrastructure as code (Bicep or Terraform) so every environment is reproducible. Deploy to a staging slot or revision, run smoke tests, then promote.
A word on cost
For a typical SaaS MVP, a single Linux App Service plan or a Container Apps environment on the consumption plan, plus Azure SQL or PostgreSQL Flexible Server, keeps monthly hosting modest. Costs usually grow from the database, logging volume and over-provisioned plans rather than from the compute choice itself. Set budgets and alerts in Azure Cost Management from the first day.
My default recommendation
Start on App Service if you have one web app or API. Move to (or start on) Container Apps when you add background workers, multiple services or event-driven scaling. Reach for AKS only when you have requirements that Container Apps can't meet and a team ready to operate Kubernetes. Because the app is containerised and configured through environment variables and managed identity, moving between them later is a deployment change, not a rewrite.
Planning a move to Azure or reviewing your current setup? See my cloud solutions service or contact me to discuss your architecture.