Azure Container Apps (ACA) has become my go-to platform for deploying .NET microservices. It offers the right balance between simplicity and control: you get container orchestration without managing Kubernetes directly. Here's everything I've learned from running production workloads on the platform.
What Azure Container Apps Offers
ACA sits between Azure App Service and Azure Kubernetes Service. You get container-based deployments with built-in scaling, ingress, secrets management, and Dapr integration, without writing YAML manifests or managing cluster nodes.
Key features:
- HTTP and event-driven scaling from zero to many replicas
- Built-in ingress with HTTPS termination and custom domains
- Revision management for blue-green and canary deployments
- Managed identity for secure access to other Azure resources
- Dapr sidecar for service-to-service communication (optional)
Deploying a .NET Application
The fastest path from code to ACA is the Azure Developer CLI (azd):
azd init
azd up
For more control, use the Azure CLI directly:
# Create the environment
az containerapp env create \
--name my-env \
--resource-group my-rg \
--location westeurope
# Deploy from a container image
az containerapp create \
--name my-api \
--resource-group my-rg \
--environment my-env \
--image myregistry.azurecr.io/my-api:latest \
--target-port 8080 \
--ingress external \
--min-replicas 1 \
--max-replicas 5 \
--cpu 0.5 \
--memory 1Gi
Scaling Configuration
ACA supports multiple scaling triggers. The most common for web APIs is HTTP-based scaling:
az containerapp update \
--name my-api \
--resource-group my-rg \
--scale-rule-name http-scaling \
--scale-rule-type http \
--scale-rule-http-concurrency 50 \
--min-replicas 1 \
--max-replicas 10
This scales up when concurrent requests per replica exceed 50. For background workers, you can scale on queue length, custom metrics, or KEDA-supported event sources.
Scaling to zero is supported and eliminates costs during idle periods, but adds cold-start latency. For production APIs, I recommend setting min-replicas to at least 1.
Secrets and Configuration
ACA has a built-in secrets store, but I prefer using Azure Key Vault with managed identity for production:
# Enable managed identity
az containerapp identity assign \
--name my-api \
--resource-group my-rg \
--system-assigned
# Reference Key Vault secrets
az containerapp update \
--name my-api \
--resource-group my-rg \
--set-env-vars \
"ConnectionStrings__Database=secretref:db-connection-string"
In your .NET code, the Key Vault configuration provider loads secrets transparently:
builder.Configuration.AddAzureKeyVault(
new Uri(builder.Configuration["KeyVault:Url"]!),
new DefaultAzureCredential());
Health Probes
Configure liveness and readiness probes to ensure ACA routes traffic correctly:
{
"probes": [
{
"type": "liveness",
"httpGet": {
"path": "/alive",
"port": 8080
},
"periodSeconds": 10
},
{
"type": "readiness",
"httpGet": {
"path": "/health",
"port": 8080
},
"periodSeconds": 5
}
]
}
ASP.NET Core's health check middleware maps naturally to these probes. The readiness probe should verify database connectivity, while the liveness probe should be a simple check that the process is running.
Multi-Service Architecture
For applications with multiple services, use an ACA environment to group them. Services within the same environment can communicate via internal ingress:
# Internal service (not publicly accessible)
az containerapp create \
--name my-worker \
--environment my-env \
--ingress internal \
--target-port 8080
Services discover each other by name within the environment. The URL pattern is https://my-worker.internal.<env-domain>.
.NET Aspire Integration
If you're using .NET Aspire, deployment to ACA is nearly automatic. The Aspire AppHost generates the required Bicep templates:
azd init
azd up
Aspire maps each project and container resource to an ACA instance, configures service discovery, provisions databases and caches, and wires up monitoring through Application Insights. This is by far the smoothest deployment experience I've used for .NET distributed applications.
Cost Optimization Tips
ACA uses a consumption-based pricing model. To control costs:
- Set
max-replicasbased on actual load testing, not theoretical maximums - Use scale-to-zero for development and staging environments
- Choose the right CPU and memory allocation; over-provisioning wastes money
- Monitor with Azure Cost Management and set budget alerts
Azure Container Apps strikes the right balance for most .NET workloads. You get the benefits of containerization without the operational complexity of Kubernetes, and the integration with the .NET ecosystem continues to improve with each release.

Comments (2)
I tried this approach and it works perfectly!
I had the same experience, can confirm.
Well written and easy to follow. Keep it up!
Leave a comment