Azure offers compute from full VMs down to functions that run only when triggered. Pick by how much you want to manage.
Services: Virtual Machines, VM Scale Sets, App Service, Container Instances, Container Registry (ACR), Kubernetes Service (AKS), Container Apps, Functions, Logic Apps, Batch, Virtual Desktop.
| Option | Model | You manage |
|---|---|---|
| Virtual Machines | IaaS | OS, patches, runtime, app |
| VM Scale Sets | IaaS | Same, but many identical VMs with autoscale |
| Azure App Service | PaaS | App code only |
| Container Instances (ACI) | CaaS | Container image |
| Azure Kubernetes Service (AKS) | Managed K8s | Workloads (Azure runs the control plane) |
| Container Apps | Serverless containers | Container image |
| Azure Functions | FaaS | Function code |
| Azure Virtual Desktop | Desktop as a service | Session hosts / images |
Virtual Machines
You choose OS, size, disks and network. You pay for compute while the VM is allocated; disks cost even when it is stopped.
$ az vm create \
--resource-group rg-demo --name vm-web \
--image Ubuntu2204 --size Standard_B2s \
--admin-username azureuser --generate-ssh-keys
$ az vm list -o table
$ az vm deallocate -g rg-demo -n vm-web # stops compute billing
$ az vm start -g rg-demo -n vm-web
VM sizes (families)
- B: burstable, cheap, dev/test
- D: general purpose
- E: memory optimised
- F: compute optimised
- N: GPU
- L: storage optimised
Stopped vs deallocated
- Stopped from inside the OS: still allocated, still billed
- Deallocated via Azure: compute released, no compute charge
Resilience for VMs
- Availability zones: spread across datacenters in a region
- Availability sets: spread across fault/update domains in one datacenter
- Scale Sets: auto add/remove instances based on metrics or schedule
- Reserved Instances / Savings Plans: 1 or 3 year commitment for large discounts
- Spot VMs: spare capacity at deep discount, can be evicted
Azure App Service
PaaS for web apps, REST APIs and mobile back ends. Supports .NET, Java, Node.js, Python, PHP and containers.
- Runs inside an App Service plan that defines region, OS, size and scale
- Deployment slots (staging, production) with swap for zero-downtime deploys
- Built-in autoscale, custom domains, TLS, authentication, CI/CD from GitHub / Azure DevOps
$ az appservice plan create -g rg-demo -n plan-web --sku B1 --is-linux
$ az webapp create -g rg-demo -p plan-web -n my-unique-webapp --runtime "NODE:20-lts"
$ az webapp deployment slot create -g rg-demo -n my-unique-webapp --slot staging
Containers
Azure Container Instances (ACI)
Run a container with no VM to manage. Billed per second. Good for short tasks and bursts.
$ az container create -g rg-demo -n aci-demo --image nginx --dns-name-label my-aci --ports 80
Azure Container Registry (ACR)
Private registry for images (like Docker Hub, but yours).
$ az acr create -g rg-demo -n myregistry123 --sku Basic
$ az acr build -r myregistry123 -t myapp:v1 .
Azure Kubernetes Service (AKS)
Azure runs the control plane for free; you pay for the node pools. See 2. Kubernetes Architecture – from Container Images to Running Pods.
$ az aks create -g rg-demo -n aks-demo --node-count 2 --generate-ssh-keys
$ az aks get-credentials -g rg-demo -n aks-demo
Azure Container Apps
Serverless containers built on Kubernetes, with scale to zero and event-driven scaling (KEDA). No cluster to run.
Azure Functions
Event-driven serverless code. Execution is started by a trigger and can read/write data through bindings.
| Trigger | Fires on |
|---|---|
| HTTP | An HTTP request |
| Timer | A CRON schedule |
| Blob | A blob created / updated |
| Queue / Service Bus | A message arrives |
| Event Grid / Event Hubs | An event arrives |
| Cosmos DB | A change feed entry |
Hosting plans
| Plan | Scale | Notes |
|---|---|---|
| Consumption | To zero, automatic | Pay per execution, cold starts, 5 min default timeout |
| Flex Consumption | Automatic, per-function | Faster scale, VNet support |
| Premium | Pre-warmed instances | No cold start, VNet, longer runtime |
| Dedicated (App Service) | Manual / autoscale | Use spare App Service capacity |
import azure.functions as func
app = func.FunctionApp()
@app.route(route="hello", auth_level=func.AuthLevel.FUNCTION)
def hello(req: func.HttpRequest) -> func.HttpResponse:
name = req.params.get("name", "world")
return func.HttpResponse(f"Hello, {name}")
Durable Functions
Extension for stateful workflows in code: function chaining, fan-out/fan-in, human approval, long-running monitors.
Choosing Compute
- Lift-and-shift legacy app → VM
- Standard web app / API → App Service
- Microservices needing orchestration → AKS or Container Apps
- Run a quick container job → ACI
- React to events with small code → Functions