Choosing Between VMs, Functions, and Containers in Azure
Picking the right compute service in Azure determines how much infrastructure you manage, how your application scales, and what it costs. This page cuts through the service catalog and provides a practical decision framework for choosing between Virtual Machines, Azure Functions, App Service, Container Apps, AKS, and Azure Batch — based on the actual characteristics of your workload.
The management spectrum
Azure compute options sit on a spectrum from infrastructure you control to infrastructure Azure manages for you. Moving right on the spectrum reduces operational work but also reduces low-level control:
| Service | You manage | Azure manages |
|---|---|---|
| Virtual Machines | OS, runtime, patches, scaling, everything inside the VM | Physical host, hypervisor |
| VM Scale Sets | OS, runtime, patches — scaling is automated | Physical host, instance lifecycle |
| AKS | Kubernetes config, node pools, cluster upgrades | Control plane, physical hosts |
| App Service / Container Apps | App code or container image and config | OS, runtime, scaling, TLS, load balancing |
| Azure Functions | Function code and bindings | OS, runtime, scaling, infrastructure, billing |
| Azure Batch | Pool config, task definitions | Job scheduling, node management, retries |
The general principle: start as far right as possible (most managed), and move left only when a specific capability requires it.
Decision by workload type
HTTP web application or REST API
First choice: App Service. Managed TLS, deployment slots, autoscaling, and multiple runtime support with no infrastructure work. If the API is containerised, use App Service with a container image or Azure Container Apps if you need to scale to zero between requests. AKS only if you have an existing Kubernetes requirement or need advanced traffic management.
Event-triggered short-lived tasks (under 10 minutes)
First choice: Azure Functions (Consumption plan). Reacts to queue messages, HTTP webhooks, blob events, schedules. Bills per execution — near-zero cost for intermittent workloads. If cold starts are unacceptable, use Functions Premium plan. If tasks exceed 10 minutes, use a Dedicated plan or switch to Azure Batch or Container Apps for longer jobs.
Microservices architecture
First choice: Azure Container Apps. Multiple independently scalable services, service-to-service networking, traffic splitting for canary deployments, KEDA-powered event-driven scaling. Requires containerisation but eliminates cluster management. Use AKS when you need direct Kubernetes API access, custom operators, or service mesh (Istio).
Lift-and-shift from on-premises
First choice: Azure VMs. Replicate your existing server environment without rewriting the application. Use Azure Migrate to assess and move workloads. After migrating, evaluate whether refactoring to App Service or Functions makes sense — but the initial move is to VMs.
Large-scale batch processing (minutes to hours per task)
First choice: Azure Batch. Manages a pool of VMs, distributes tasks, handles retries. Use low-priority nodes for fault-tolerant workloads at 80% cost reduction. If tasks run under 10 minutes and do not need GPU or full OS access, Azure Functions with queue triggers may be simpler.
Scheduled jobs and cron tasks
First choice: Azure Functions (Timer trigger). Cheapest option for periodic tasks that run for seconds to minutes. For jobs that take longer or require a full VM environment, use Azure Batch with a scheduled trigger or Azure Logic Apps to invoke Batch on a schedule.
Decision by team capability
Technical capability should influence the choice. A service that the team cannot operate effectively is not the right choice regardless of its theoretical advantages.
| If your team knows… | Start with… |
|---|---|
| Traditional server administration, Linux/Windows | Azure VMs — familiar model, lowest learning curve |
| Web development, but no cloud experience | App Service — deploy your code, Azure handles the rest |
| Docker, containers | Azure Container Apps or App Service (container) |
| Kubernetes | AKS — familiar operational model |
| Serverless / event-driven patterns | Azure Functions — directly applicable skills |
| HPC, scientific computing | Azure Batch — designed for parallel compute workloads |
Cost patterns by service
Cost depends heavily on usage pattern. Three representative scenarios:
Scenario 1: Low-traffic API (1 million requests/month)
- Azure Functions Consumption: ~$0.20/month (1M requests, short execution time)
- App Service B1: ~$13/month (always-on dedicated compute)
- VM (Standard_B1s): ~$8/month (same idle-time cost whether or not traffic comes)
Functions wins for low-traffic, intermittent use. App Service wins when always-on behaviour is needed and traffic is consistent.
Scenario 2: High-traffic API (500M requests/month)
- Azure Functions Consumption: ~$100/month
- App Service Standard S2 (2 instances): ~$200/month
- At very high scale, App Service on a plan becomes cheaper than per-execution Functions billing
Scenario 3: Nightly batch job (2 hours/night)
- Azure Batch with 10 Standard_D4s_v5 low-priority nodes: ~$15/month
- Always-on VM Scale Set: ~$400/month (10 VMs running 24/7)
On-demand provisioning for batch workloads is dramatically cheaper than always-on capacity.
Quick decision checklist
Answer these questions in order. Stop at the first match.
- Do you need OS-level control, custom kernel modules, or are you lifting a legacy workload? → Virtual Machines
- Is it a web app or API where you want managed TLS, deployment slots, and no server config? → App Service
- Is it an event-triggered task under 10 minutes that runs occasionally? → Azure Functions
- Is it a containerised workload that needs to scale to zero and communicate with other services? → Azure Container Apps
- Do you need full Kubernetes control, custom operators, or have existing Kubernetes expertise? → AKS
- Is it a large-scale parallel job with tasks that run for minutes to hours? → Azure Batch
- Is it a complex multi-step integration workflow with third-party SaaS services? → Azure Logic Apps
Common decision mistakes
- Choosing AKS for everything “because it scales”. AKS is powerful, but it requires Kubernetes expertise to operate correctly — version upgrades, node pool management, storage class configuration, ingress setup. Most workloads do not need this complexity. Use Container Apps or App Service, and graduate to AKS only when a specific Kubernetes feature is required.
- Running scheduled jobs on always-on VMs. A VM running a 2-hour nightly job still incurs 22 hours of idle compute cost. Use Azure Batch, Azure Functions (timer trigger), or Azure Container Apps (jobs mode) so you pay only when the job runs.
- Treating the compute choice as permanent. You can migrate workloads between compute services — it requires effort, but it is not a one-time irreversible decision. Start with the simplest option that works, observe real production behaviour, and move to a different service if the original choice has clear limitations that matter for your use case.
Summary
- Start with the most managed option that satisfies your requirements — App Service or Functions for most web workloads, Container Apps for containerised microservices.
- Move left toward VMs or AKS only when you have a specific requirement that managed services cannot meet: OS-level control, custom Kubernetes features, or legacy workload migration.
- Cost depends on usage pattern. Functions is cheapest for intermittent workloads; reserved VMs are cheaper at high sustained load; Batch with low-priority nodes is cheapest for large-scale parallel processing.
- Team capability matters. A team without Kubernetes experience running AKS will pay operational costs in engineer time even if the Azure bill is reasonable.
- Combining compute services in one application is common and often the right approach — use the service that fits each workload type.
Frequently asked questions
Is it possible to use multiple compute types in the same application?
Yes, and it is common. A web application might run on App Service (managed web platform), use Azure Functions for async background processing, and store results in a managed database. The front-end API, the background workers, and the data layer all use different compute models because each matches the workload better.
Which Azure compute option is cheapest?
Azure Functions on the Consumption plan is the cheapest for intermittent workloads — you pay only for execution time, and the first million executions per month are free. For long-running, consistent workloads, a reserved VM instance often beats Functions at high scale. Containers on Container Apps Consumption plan are middle-ground. There is no universally cheapest option — cost depends on workload characteristics.
What should a beginner start with when learning Azure compute?
Start with Azure App Service for web applications and Azure Functions for event-driven tasks. These two services cover the majority of common workloads, have the lowest operational overhead, and teach the key patterns (managed runtimes, event triggers, scaling) that transfer to more complex services. Move to AKS or VMs only when you have a specific need that App Service or Functions cannot meet.