Azure Container Apps Overview: Scalable Microservices Without Kubernetes
Azure Container Apps runs containerised applications with automatic scaling, built-in traffic management, and event-driven scale triggers — without requiring you to manage Kubernetes clusters, node pools, or control planes. It is the managed container platform between simple App Service and full AKS, designed for microservices architectures where teams want container portability without infrastructure complexity. This page explains the architecture, key features, and when Container Apps is the right choice.
What Container Apps provides
Container Apps combines several capabilities that would otherwise require separate services or significant configuration on raw Kubernetes:
- Scale to zero and scale out. Apps scale based on HTTP traffic, event queue depth, or custom metrics. During quiet periods, apps scale to zero and consume no compute resources — you pay nothing while idle.
- Traffic splitting. Route a percentage of traffic to different container revisions — enabling blue-green deployments and canary releases without external load balancers or Kubernetes ingress configuration.
- Dapr integration. Built-in support for Dapr sidecars, which provide service invocation, pub/sub messaging, state management, and secret management as distributed application patterns without writing infrastructure code.
- KEDA event-driven scaling. Scale based on Azure Service Bus queue depth, Event Hubs event count, Redis queue length, or any KEDA-supported trigger. Event-driven scaling without writing autoscale rules.
- Managed certificates and ingress. HTTP ingress with managed TLS, configurable from the portal or CLI. No ingress controller configuration required.
- VNet integration. Apps in an environment can join a VNet for private access to databases and internal services.
Environments and Container Apps
Container Apps are deployed into a Container Apps Environment — a shared boundary for a group of related apps. Apps within the same environment can communicate with each other over a private internal network by name. Apps in different environments are isolated.
Think of an environment as a logical cluster. A typical setup has one environment per stage: a development environment, a staging environment, and a production environment. Within the production environment, all the microservices of an application run side by side and discover each other internally.
# Create a Container Apps Environment
az containerapp env create \
--name my-prod-env \
--resource-group my-rg \
--location eastus
# Create a Container App in that environment
az containerapp create \
--name my-api \
--resource-group my-rg \
--environment my-prod-env \
--image myorgacr.azurecr.io/myapi:latest \
--cpu 0.5 \
--memory 1Gi \
--min-replicas 1 \
--max-replicas 10 \
--ingress external \
--target-port 8080 \
--registry-server myorgacr.azurecr.ioThe —ingress external flag makes the app reachable from the internet. Use —ingress internal for services that should only be reachable from other apps within the same environment.
Scaling rules
Container Apps uses KEDA for scaling. You can add multiple scale rules to a single app:
# Scale based on HTTP concurrent requests (built-in)
az containerapp update \
--name my-api \
--resource-group my-rg \
--min-replicas 0 \
--max-replicas 20 \
--scale-rule-name http-rule \
--scale-rule-type http \
--scale-rule-http-concurrency 20The —scale-rule-http-concurrency 20 configuration means: add a new replica when more than 20 concurrent requests are being handled. With 100 simultaneous requests, Container Apps scales to 5 replicas. Scale in happens when concurrency drops back below the threshold.
For queue-based workers, scale on queue depth:
# Add a Service Bus queue scale rule to a worker app
az containerapp update \
--name my-worker \
--resource-group my-rg \
--min-replicas 0 \
--max-replicas 50 \
--scale-rule-name sb-rule \
--scale-rule-type azure-servicebus \
--scale-rule-metadata "queueName=work-queue" "messageCount=10" \
--scale-rule-auth "connection=SERVICE_BUS_CONNECTION"One replica is added for every 10 messages in the queue, up to 50 replicas. When the queue empties, replicas scale back to zero — you pay nothing between processing runs.
Traffic splitting and revisions
Every deployment to a Container App creates a new revision. Revisions are immutable — you cannot modify a running revision’s image or configuration. Traffic can be split between revisions, enabling gradual rollouts:
# Deploy a new container image as a new revision
az containerapp update \
--name my-api \
--resource-group my-rg \
--image myorgacr.azurecr.io/myapi:v2.0.0
# Split traffic: send 10% to the new revision, 90% to the previous one
az containerapp ingress traffic set \
--name my-api \
--resource-group my-rg \
--revision-weight \
my-api--revision-v1=90 \
my-api--revision-v2=10This canary deployment pattern lets you validate the new version with real traffic before fully switching over. Monitor error rates and latency in Application Insights, then gradually shift the traffic percentage to 100% on the new revision.
Container Apps Jobs
Container Apps also supports Jobs — containers that run to completion rather than staying running to serve requests. Jobs are useful for batch processing, scheduled tasks, and event-driven processing where each work item runs a container instance to completion.
# Create a scheduled job that runs every day at midnight
az containerapp job create \
--name nightly-processor \
--resource-group my-rg \
--environment my-prod-env \
--image myorgacr.azurecr.io/processor:latest \
--cpu 1 \
--memory 2Gi \
--trigger-type Schedule \
--cron-expression "0 0 * * *" \
--replica-completion-count 1 \
--parallelism 1Jobs scale independently from services — you can configure a job to run in parallel across many replicas for bulk processing workloads, then scale to zero between runs.
Consumption versus Dedicated plans
Container Apps Environments offer two billing models:
Consumption plan
Pay per vCPU-second and GB-second of memory used while replicas are running. Scale to zero = zero cost. The first 180,000 vCPU-seconds and 360,000 GB-seconds per month are free. Good for development environments, bursty workloads, and services that scale to zero during off-hours.
Dedicated plan
Your apps run on dedicated compute nodes (similar to an App Service Plan). Predictable cost, no cold starts, and support for larger workload profiles. Better for high-traffic services where the per-second billing of Consumption would exceed the fixed node cost.
Common Container Apps mistakes
- Setting min-replicas to 0 for latency-sensitive APIs. Scale-to-zero is great for cost but means the first request after an idle period waits for a cold start — typically 3–10 seconds. For user-facing APIs where sub-second response is expected, set min-replicas to at least 1.
- Not setting resource limits. Container Apps without CPU and memory limits can consume more resources than expected during traffic spikes, potentially causing noisy-neighbour effects in the environment or exceeding your budget. Set appropriate CPU and memory values for your workload and tune based on observed usage.
- Expecting direct Kubernetes access. Container Apps hides the Kubernetes API completely. If your team has built tooling around kubectl, Helm charts, or custom Kubernetes operators that rely on direct API access, Container Apps will not work as a drop-in replacement. AKS is the appropriate choice in that case.
Summary
- Container Apps runs containerised microservices with automatic scaling, traffic splitting, and KEDA event-driven scaling — without Kubernetes cluster management.
- Apps deploy into an Environment. Apps in the same environment communicate internally by name; external ingress is managed with automatic TLS.
- Scale to zero on Consumption plan means zero cost during idle periods. Set min-replicas to 1 for latency-sensitive services to avoid cold starts.
- Traffic splitting between revisions enables canary deployments and blue-green releases without load balancer configuration.
- Container Apps Jobs run containers to completion — useful for scheduled batch tasks and event-driven processing without a persistent service.
Frequently asked questions
What is the difference between Azure Container Apps and AKS?
AKS gives you a full Kubernetes cluster — direct kubectl access, custom operators, cluster networking configuration. Container Apps uses Kubernetes internally but hides the cluster management entirely. You cannot access the Kubernetes API. Container Apps is simpler to operate but less flexible — use AKS when you need features Container Apps does not expose (custom CRDs, Istio, advanced networking), and Container Apps for everything else.
Can Azure Container Apps scale to zero?
Yes. On the Consumption plan, Container Apps scales to zero when there are no requests. When traffic arrives, a new instance starts (cold start time is typically 2–10 seconds). For apps that cannot tolerate cold starts, set a minimum of 1 replica. The Dedicated plan keeps instances warm.
Does Container Apps support multiple containers in one app?
Yes. Each Container App can have multiple containers configured as sidecars — they run in the same container group, share a network namespace, and communicate via localhost. Common patterns include a Dapr sidecar for distributed application features, a log shipper sidecar, or an envoy proxy alongside the main application container.