Skip to main content
All posts
Cloud Architecture10 min read

Azure Container Apps vs. AKS vs. Azure Functions: A Decision Tree for 2026

A practical decision tree comparing Azure Container Apps, AKS, and Azure Functions across operational complexity, scaling, cost, networking, and compliance for enterprise workloads.

Published

Azure offers at least six ways to run application code: Virtual Machines, App Service, Azure Functions, Container Instances, Container Apps, and Azure Kubernetes Service. This abundance of choice paralyses teams who spend weeks debating compute platforms instead of building features.

This guide narrows the decision to the three most relevant options for modern enterprise workloads in 2026: Azure Container Apps (ACA), Azure Kubernetes Service (AKS), and Azure Functions. We provide a clear decision tree, honest trade-offs, and specific guidance on when to use each — and when to combine them.

The Decision Tree

Answer these questions in order. The first "yes" determines your starting point.

Loading diagram...

This is deliberately simple. The rest of this article provides the nuance behind each decision point.

Comparison Matrix

DimensionAzure Container AppsAKSAzure Functions
Abstraction levelManaged containersManaged KubernetesServerless functions
Operational complexityLowHighVery low
Scaling modelKEDA-based, scale-to-zeroHPA/VPA/KEDA, node autoscalerEvent-driven, scale-to-zero
Cold start5-15 secondsNone (always running)1-10 seconds (Consumption), none (Premium)
Max execution timeUnlimited (dedicated)Unlimited10 min (Consumption), unlimited (Premium)
NetworkingVNet injection, managed ingressFull VNet, any CNI, network policiesVNet integration (Premium only)
Dapr integrationBuilt-in, first-classManual installationNot available
KEDA integrationBuilt-inManual installationBuilt-in (limited triggers)
GPU supportNoYesNo
Custom domains / TLSBuilt-in, managed certificatesManual or cert-managerBuilt-in (Premium)
Min cost (idle)EUR 0 (scale-to-zero)EUR 150+/month (min nodes)EUR 0 (Consumption plan)
Compliance controlsManaged environmentFull infrastructure controlPlatform-managed
Container runtimecontainerd (managed)containerd (configurable)N/A (code-based)

Azure Container Apps: The New Default

Container Apps has matured significantly since its 2022 launch. For most containerised workloads that do not need the full Kubernetes API, it is now the default recommendation.

What Container Apps does well

Automatic scaling with KEDA. Container Apps uses KEDA (Kubernetes Event-Driven Autoscaling) under the hood, supporting 60+ scalers: HTTP requests, Azure Service Bus queue depth, Cosmos DB change feed, Kafka topics, cron schedules, and more.

YAML
# Container Apps scaling configuration
properties:
  template:
    scale:
      minReplicas: 0
      maxReplicas: 30
      rules:
        - name: http-scaling
          http:
            metadata:
              concurrentRequests: '50'
        - name: queue-scaling
          azureQueue:
            queueName: orders
            queueLength: 10
            auth:
              - secretRef: queue-connection
                triggerParameter: connection

Built-in Dapr integration. Dapr (Distributed Application Runtime) provides service invocation, state management, pub/sub messaging, and secret management through a sidecar pattern. On AKS, you install and manage Dapr yourself. On Container Apps, it is a checkbox.

YAML
# Dapr configuration in Container Apps
properties:
  configuration:
    dapr:
      enabled: true
      appId: order-service
      appProtocol: http
      appPort: 8080
      enableApiLogging: true

Managed ingress with traffic splitting. Blue/green and canary deployments are built-in via revision management and traffic splitting — no need for Istio or Nginx ingress controllers.

Bash
# Traffic splitting between revisions
az containerapp ingress traffic set \
  --name order-api \
  --resource-group rg-production \
  --revision-weight latest=20 order-api--v1=80

What Container Apps does not do well

  • No Kubernetes API access. You cannot use kubectl, Helm charts, or Kubernetes operators. If your CI/CD pipeline or tooling depends on the Kubernetes API, Container Apps requires rethinking.
  • No GPU workloads. ML inference, video transcoding, or any GPU-dependent workload requires AKS or VMs.
  • Limited networking. No Kubernetes network policies, no custom CNI plugins. You get VNet injection and managed ingress, but not the networking flexibility of AKS.
  • No DaemonSets or privileged containers. System-level workloads like log collectors, security agents, or node-level monitoring agents cannot run on Container Apps.

Cost profile

Container Apps pricing is based on vCPU and memory consumption per second, plus HTTP requests for ingress. Scale-to-zero means idle workloads cost nothing.

Code
Example: API serving 100,000 requests/day
- Average 2 replicas, 0.5 vCPU / 1 GB each
- Active 16 hours/day, scaled to zero overnight
- Monthly cost: ~EUR 45 (vCPU/memory) + EUR 5 (requests) = EUR 50

The same workload on AKS would cost EUR 150-200/month minimum for the node pool, plus the EUR 0.10/hour cluster management fee.

AKS: When You Need the Full Kubernetes

AKS remains the right choice when your workload genuinely needs Kubernetes features that Container Apps cannot provide.

When AKS is justified

Custom operators and CRDs. If you use operators like Strimzi (Kafka), Prometheus Operator, Cert-Manager, or custom CRDs, you need the Kubernetes API.

Service meshes. Istio, Linkerd, or Consul for advanced traffic management, mTLS, and observability. Container Apps provides basic traffic splitting but not the full service mesh feature set.

GPU workloads. ML model inference, batch processing with GPUs, or any CUDA-dependent workload.

Multi-cluster federation. Active-active deployments across regions with consistent service discovery and configuration.

Compliance requirements. Some compliance frameworks require infrastructure-level control that Container Apps' managed environment cannot provide. If you need to specify exact node OS images, kernel parameters, or run CIS benchmarks against nodes, AKS is necessary.

The hidden cost of AKS

The AKS management fee is EUR 0.10/hour (EUR 73/month). This is the visible cost. The hidden costs are:

Code
AKS cluster management fee:        EUR     73/month
Node pool (3x D4s_v5, min):        EUR    450/month
Load balancer:                      EUR     18/month
Managed disks (OS + data):          EUR     60/month
Log Analytics workspace:            EUR    100/month (typical)
Container Insights:                 EUR     50/month (typical)
Platform engineer (0.5 FTE):        EUR  4,500/month
Training and certifications:        EUR    200/month (amortised)
Security tooling (Defender):        EUR     75/month
------------------------------------------------------
Total:                              EUR  5,526/month

That EUR 73/month cluster fee becomes EUR 5,500/month when you account for everything needed to run AKS in production. This is why Container Apps at EUR 50-200/month is often the right answer.

AKS configuration for production

Bicep
resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-01-01' = {
  name: 'aks-production'
  location: 'westeurope'
  identity: { type: 'SystemAssigned' }
  properties: {
    kubernetesVersion: '1.29'
    dnsPrefix: 'aks-prod'
    networkProfile: {
      networkPlugin: 'azure'
      networkPolicy: 'calico'
      serviceCidr: '10.0.0.0/16'
      dnsServiceIP: '10.0.0.10'
      loadBalancerSku: 'Standard'
    }
    agentPoolProfiles: [
      {
        name: 'system'
        count: 3
        vmSize: 'Standard_D4s_v5'
        availabilityZones: ['1', '2', '3']
        mode: 'System'
        osSKU: 'AzureLinux'
        enableAutoScaling: true
        minCount: 3
        maxCount: 5
      }
      {
        name: 'workload'
        count: 3
        vmSize: 'Standard_D8s_v5'
        availabilityZones: ['1', '2', '3']
        mode: 'User'
        osSKU: 'AzureLinux'
        enableAutoScaling: true
        minCount: 2
        maxCount: 20
      }
    ]
    addonProfiles: {
      azureKeyvaultSecretsProvider: { enabled: true }
      omsagent: {
        enabled: true
        config: { logAnalyticsWorkspaceResourceID: logAnalyticsId }
      }
    }
    autoUpgradeProfile: { upgradeChannel: 'stable' }
    securityProfile: {
      defender: { securityMonitoring: { enabled: true } }
      workloadIdentity: { enabled: true }
    }
    oidcIssuerProfile: { enabled: true }
  }
}

Azure Functions: Event-Driven Glue

Azure Functions is not a general-purpose compute platform. It is optimised for event-driven, short-lived executions. Using it as a general-purpose API backend leads to pain.

When Functions is the right choice

  • Event processing: Service Bus message handlers, Event Grid subscribers, Cosmos DB change feed processors
  • Scheduled tasks: Cron-based cleanup jobs, report generation, data synchronisation
  • Lightweight APIs: Simple REST endpoints with low traffic that benefit from scale-to-zero
  • Integration glue: Connecting SaaS services, transforming data between systems, webhook handlers

When Functions is the wrong choice

  • Long-running processes: Anything exceeding 10 minutes on Consumption plan (use Durable Functions or Container Apps)
  • Stateful workloads: Functions are stateless by design (Durable Functions add state but with complexity)
  • High-throughput APIs: Cold starts on Consumption plan create latency spikes. Premium plan eliminates cold starts but at EUR 150+/month minimum
  • Complex microservices: If you need sidecar patterns, service discovery, or inter-service communication, use Container Apps

Functions hosting plans comparison

PlanCold StartMin CostMax InstancesTimeoutVNet
Consumption1-10 secEUR 020010 minNo
Flex Consumption0-1 secEUR 01000UnlimitedYes
Premium (EP1)NoneEUR 150/month100UnlimitedYes
Dedicated (App Service)NoneEUR 50+/month30UnlimitedYes

Functions with KEDA triggers

Csharp
// Azure Function with Service Bus trigger
[Function("ProcessOrder")]
public async Task Run(
    [ServiceBusTrigger("orders", Connection = "ServiceBusConnection")]
    ServiceBusReceivedMessage message,
    ServiceBusMessageActions messageActions,
    FunctionContext context)
{
    var logger = context.GetLogger("ProcessOrder");
    var order = JsonSerializer.Deserialize<Order>(message.Body);

    try
    {
        await _orderService.ProcessAsync(order);
        await messageActions.CompleteMessageAsync(message);
        logger.LogInformation("Order {OrderId} processed", order.Id);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Failed to process order {OrderId}", order.Id);
        // Message will be retried based on Service Bus retry policy
        throw;
    }
}

When to Combine Services

The best architectures often use multiple compute services. Here is a proven pattern:

Loading diagram...

Container Apps handles the stateless API layer with automatic scaling and managed ingress.

Azure Functions processes asynchronous events from Service Bus, Event Grid, and Cosmos DB change feeds.

AKS runs workloads that need GPUs, custom operators, or the full Kubernetes API.

This is not over-engineering — it is using each service for what it does best. The key is clear boundaries: synchronous APIs go to Container Apps, asynchronous events go to Functions, and anything needing Kubernetes goes to AKS.

Complexity vs. Control Trade-Off

Loading diagram...

Migration Paths

From AKS to Container Apps

If you are running simple workloads on AKS that do not use Kubernetes-specific features, Container Apps can reduce operational burden and cost.

  1. Inventory all Kubernetes features used (CRDs, operators, network policies, node access)
  2. Identify workloads that only use basic Deployments, Services, and ConfigMaps
  3. Convert Kubernetes manifests to Container Apps configuration (Dapr annotations map directly)
  4. Migrate one workload at a time, starting with the simplest

From App Service to Container Apps

Container Apps is the natural evolution from App Service for containerised workloads that need finer scaling control.

  1. Containerise the application if not already
  2. Configure KEDA scaling rules (HTTP scaler replaces App Service auto-scale)
  3. Migrate custom domains and managed certificates
  4. Verify VNet integration works with private endpoints

Cost Optimisation Decision Framework

Monthly BudgetTeam SizeWorkload TypeRecommendation
< EUR 200No platform teamAPIs, microservicesContainer Apps
< EUR 200No platform teamEvent processingAzure Functions
EUR 200-2,0001-2 engineersMixed workloadsContainer Apps + Functions
EUR 2,000-10,0003-5 engineersComplex, multi-serviceEvaluate AKS vs Container Apps
> EUR 10,000Dedicated platform teamEnterprise platformAKS + Container Apps + Functions

Next Steps

The compute platform decision should take hours, not weeks. Use the decision tree above, evaluate honestly whether your workloads need Kubernetes features, and default to the simplest option that meets your requirements.

If you are running AKS and questioning whether the complexity is justified, or evaluating Container Apps for a new project, reach out at mbrahim@conceptualise.de. We help enterprises right-size their compute platform decisions — which often means simplifying from AKS to Container Apps and saving significant operational cost.

Topics

Azure Container Apps vs AKSAzure Functions comparisonKubernetes decision treeAzure compute optionsserverless vs containers Azure

Frequently Asked Questions

Choose Azure Container Apps when you need container-based workloads without the operational overhead of managing Kubernetes infrastructure. Container Apps is ideal for microservices, APIs, event-driven processing, and background jobs where you want automatic scaling including scale-to-zero, built-in Dapr support, and managed ingress without maintaining node pools, RBAC, or the Kubernetes control plane.

Expert engagement

Need expert guidance?

Our team specializes in cloud architecture, security, AI platforms, and DevSecOps. Let's discuss how we can help your organization.

Get in touchNo commitment · No sales pressure

Related articles

All posts