Episode 4 — High Availability and Scaling: Sets, Zones, and Scale Sets

In Episode 3 you learned to secure, encrypt, and administer a single VM — but a single VM, however well managed, is still a single point of failure. This episode is about making your compute survive failures and grow with demand.

Learning objectives

  • Explain what availability features protect against: planned maintenance, hardware failure, and zone outages.
  • Distinguish fault domains from update domains and predict how VMs are spread across them.
  • Choose between a single VM, an availability set, and availability zones based on SLA requirements.
  • Configure a VM Scale Set and decide between Flexible and Uniform orchestration.
  • Write a complete autoscale rule set with sensible minimum, maximum, and default instance counts.

Why it matters

Availability questions are a guaranteed presence on the AZ-104 exam, and they are the difference between an architecture that survives patch Tuesday and one that pages you at 3 a.m. Azure offers an explicit ladder of financially backed SLAs — 99.9%, 99.95%, 99.99% — and each rung has a concrete design requirement attached. Scaling is the same conversation from another angle: availability keeps you up, scaling keeps you fast — and in Azure both are built from the same ingredient, more than one VM.

What you are protecting against

Before choosing a mechanism, name the threat. Azure's availability features address three distinct failure classes:

ThreatExampleScopeAzure's answer
Planned maintenanceHost OS patching, hardware reboot wavesOne host at a timeUpdate domains
Unplanned hardware failureRack power or top-of-rack switch diesOne rackFault domains
Datacenter or zone outageCooling failure, fire, floodingWhole facilityAvailability zones
Region-wide disasterMajor natural disasterWhole regionMulti-region design (beyond this episode)

The pattern to internalize: each mechanism protects a larger blast radius, and each larger blast radius requires your VMs to be spread physically further apart. If both your VMs share a rack, no software setting saves you when that rack loses power.

Fault domains and update domains

An availability set is a logical grouping you assign VMs to at creation time (you cannot add an existing VM to one later). Inside the set, Azure spreads your VMs across two independent grids:

  • A fault domain (FD) is a set of hardware that shares a common power source and network switch — think "a rack." If the rack fails, every VM in that fault domain goes down together. Availability sets support up to 3 fault domains.
  • An update domain (UD) is a group of VMs that Azure may reboot together during planned maintenance. Azure walks through update domains one at a time, waiting for each to recover before touching the next. Availability sets support up to 20 update domains.

Every VM in the set gets both an FD number and a UD number, assigned round-robin:

Availability set (one datacenter)Fault domain 2VM3 UD 2Fault domain 1VM2 UD 1VM5 UD 4Fault domain 0(shared rack, power, switch)VM1 UD 0VM4 UD 3

Read the diagram both ways. Vertically: if fault domain 1 loses power, you lose VM2 and VM5, but VMs 1, 3, and 4 keep serving. Horizontally: when Azure patches update domain 3, only VM4 reboots; the other four VMs stay up. With two VMs in a set you are guaranteed they land in different fault domains and different update domains, which is exactly why the 99.95% SLA requires two or more VMs.

Memory hook — "F is for Fire, U is for Upgrade": Fault domains protect against things that burn or break (unplanned hardware trouble — power, rack, switch), while Update domains protect against things Microsoft upgrades on purpose (planned reboot waves). Fire you can't schedule; upgrades you can. And the counts rhyme with their scope: hardware racks are scarce (3 FDs), patch waves are cheap (20 UDs).

Exercise 4.1 — Who survives the patch wave?

You place 6 VMs in an availability set configured with 3 fault domains and 5 update domains. Azure begins planned maintenance. (a) What is the maximum number of your VMs that reboot at the same time? (b) Separately, a rack failure takes out one fault domain — what is the maximum number of VMs you lose?

Solution: VMs are assigned round-robin. Across 5 update domains, 6 VMs land as UD assignments 0,1,2,3,4,0 — so one update domain holds 2 VMs and the rest hold 1. (a) Planned maintenance touches one UD at a time, so at most 2 VMs reboot together. (b) Across 3 fault domains, 6 VMs land 2-2-2, so a rack failure costs you at most 2 VMs — the other 4 keep running. The lesson: the more VMs you add, the smaller each domain's share of your fleet, and the gentler any single event becomes.

Availability sets, availability zones, or a single VM?

An availability set spreads VMs across racks — but all of those racks live in the same datacenter. Availability zones go one level up: each zone is one or more physically separate datacenters within a region, with independent power, cooling, and networking. Deploy VMs into different zones (zone 1, 2, 3) and even a full datacenter outage leaves the survivors running. Not every region has zones, so check your target region before designing around them.

OptionSLA (financially backed)Protects againstRequirementsWatch out for
Single VM≥ 99.9%Nothing external — SLA only covers host connectivityPremium SSD or Ultra Disk on all disks~8.7 h/year potential downtime; no maintenance protection
Availability set≥ 99.95%Rack failure, planned maintenance2+ VMs in the same setStill one datacenter; can't join a VM after creation
Availability zones≥ 99.99%Datacenter/zone outage (plus everything above)2+ VMs across 2+ zonesSmall cross-zone latency; region must support zones

Two nuances the table can't hold. First, the single-VM SLA is conditional: it applies only when every attached disk is Premium SSD or better — a Standard HDD anywhere voids it. Second, availability sets and availability zones are mutually exclusive for a given VM: a VM is either in a set (spread across racks in one facility) or pinned to a zone (a specific facility). Zones are the stronger guarantee and the modern default where the region supports them; availability sets remain the answer where zones are unavailable or when an application is latency-sensitive enough that cross-zone round trips hurt.

Here is the decision compressed into a flowchart:

99.9% is enoughMore nines neededYesNoYesNoWhat SLA does the workloadneed?Single VM withPremium SSD or UltraDoes the region offerzones,and can the app toleratecross-zone latency?Availability zones(99.99%)Availability set(99.95%)Variable load ormany identical VMs?Use a VM Scale SetIndividual VMsbehind a load balancer

Exercise 4.2 — Design for the SLA

A customer runs a two-tier line-of-business app in West Europe: two web VMs and one database VM. The contract with their business requires 99.99% availability for the web tier. The database vendor only supports a single-instance deployment, but the customer wants "the best available protection" for it. What do you deploy, and what SLA can you honestly promise for each tier?

Solution: For the web tier, an availability set is not enough — its SLA tops out at 99.95%. You need the two web VMs in different availability zones (West Europe supports zones), which carries the 99.99% VM SLA. For the database, a single instance can never reach a multi-VM SLA regardless of where you put it. The best you can do is attach Premium SSD (or Ultra) disks to qualify for the 99.9% single-VM SLA, and pin it to one zone for clean colocation with backups. You promise 99.99% for the web tier and 99.9% for the database tier — and you flag in writing that the composite application SLA is governed by its weakest tier. Multiplying the numbers (0.9999 × 0.999) makes the point: the app as a whole sits just under 99.9%. That honest arithmetic is often what pushes customers to pressure their database vendor for a clustered option.

VM Scale Sets: availability plus elasticity

Sets and zones give you availability; VM Scale Sets (VMSS) add elasticity — a group of VMs that Azure can create, delete, and spread automatically. Instead of hand-placing VMs into domains, you declare "run between 2 and 10 instances of this," and the platform handles placement, replacement, and (optionally) scaling decisions.

A scale set runs in one of two orchestration modes, chosen at creation:

AspectFlexible (recommended default)Uniform
Instance shapeCan mix VM sizes and even hand-added standard VMsIdentical instances stamped from one model
SpreadingActs like a "super availability set" across FDs/zonesPlacement groups
VM managementEach instance is a full standard VM (all VM APIs work)Instances managed through the scale-set model
Max instances1,0001,000 (≤ 100 per single placement group)
Best forMost new workloads, mixed fleets, quorum-based appsVery large, strictly identical, stateless fleets

Flexible is the recommended starting point: you keep the operational model you already know from Episodes 2–3 (every instance is a normal VM), while gaining automatic spreading and scale. Uniform remains the classic choice for large stateless fleets where every instance is a clone and you want the tightest integration with the scale-set instance model.

Creating a zone-spanning Flexible scale set takes one command:

az vmss create \
  --resource-group myRG \
  --name myScaleSet \
  --location westeurope \
  --orchestration-mode Flexible \
  --image Ubuntu2204 \
  --vm-sku Standard_D2s_v5 \
  --instance-count 3 \
  --zones 1 2 3 \
  --admin-username azureuser \
  --generate-ssh-keys

Note the --zones 1 2 3: this single flag buys you the zone-level spreading from the previous section, applied automatically to every instance the set ever creates.

Autoscale: rules, schedules, and scale-in

Autoscale turns a scale set from "a group I resize by hand" into "a group that resizes itself." An autoscale setting has three anchor numbers plus rules:

  • Minimum — the floor; never go below this (your availability baseline, typically ≥ 2).
  • Maximum — the ceiling; caps cost even under attack or bug-induced load.
  • Default — the count used when metrics are unavailable.

Rules come in two flavors, and mature designs use both:

  • Metric-based rules react to load: "if average CPU > 70% over 10 minutes, add 2 instances." Always pair every scale-out rule with a scale-in rule, and leave a dead band between the thresholds (e.g., out at 70%, in at 30%) — symmetric thresholds cause flapping, where the set oscillates between adding and removing instances. A cooldown period after each action gives new instances time to absorb load before the next evaluation.
  • Schedule-based rules act on known patterns: "weekdays 08:00–18:00, minimum 4 instances." If you can predict the load, scheduling beats reacting — instances are already warm when users arrive.

The CLI shape mirrors the concepts directly:

az monitor autoscale create \
  --resource-group myRG \
  --resource myScaleSet \
  --resource-type Microsoft.Compute/virtualMachineScaleSets \
  --name cpu-autoscale \
  --min-count 2 \
  --max-count 10 \
  --count 3

az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name cpu-autoscale \
  --condition "Percentage CPU > 70 avg 10m" \
  --scale out 2

az monitor autoscale rule create \
  --resource-group myRG \
  --autoscale-name cpu-autoscale \
  --condition "Percentage CPU < 30 avg 10m" \
  --scale in 1

Scale-in behavior deserves attention because it deletes running VMs. The default scale-in policy first rebalances (removing instances so zones and fault domains stay even), then removes the instance with the highest instance ID — in practice, the newest. You can switch the policy to explicitly remove the newest VM or the oldest VM instead, and you can flag individual instances with scale-in protection so autoscale never deletes them (useful for a node holding state or a debugging session). The deeper lesson: scale sets assume stateless instances — anything worth keeping belongs on external storage, not on the VM that autoscale may delete in ten minutes.

Exercise 4.3 — Write the autoscale rule set

An e-commerce web tier runs on a Flexible scale set. Requirements: never fewer than 2 instances; finance caps the fleet at 8; traffic spikes hard during lunch (12:00–14:00) every weekday; outside known patterns, CPU should drive scaling. Draft the autoscale design: min/max/default plus the rules, with thresholds.

Solution: Anchors: min = 2 (availability floor), max = 8 (the finance cap), default = 2 (safe state if metrics go dark). Rules: (1) a schedule-based profile for weekdays 11:45–14:15 raising the minimum to, say, 4 — starting 15 minutes early so instances are warm before the spike, not during it; (2) a metric scale-out rule: average CPU > 70% over 10 minutes → add 2 (adding two absorbs sharp spikes faster than one-at-a-time); (3) a metric scale-in rule: average CPU < 30% over 10 minutes → remove 1, with a cooldown of 10+ minutes. The asymmetry is deliberate: scale out aggressively, scale in cautiously — adding an unneeded instance costs cents, removing a needed one costs customers. The 70/30 dead band prevents flapping.

Vertical vs horizontal scaling

Everything above is horizontal scaling (scale out/in): adding or removing instances. Its sibling is vertical scaling (scale up/down): changing a VM's size, as you did when resizing in Episode 3. The trade-offs are worth stating crisply:

Vertical (up/down)Horizontal (out/in)
MechanismChange VM sizeAdd/remove instances
DisruptionRequires a rebootNone for existing instances
CeilingThe biggest VM size available~1,000 instances per scale set
Availability effectNone — still one VMImproves it — more instances, more domains
App requirementsWorks for any app, including stateful legacyNeeds stateless, load-balanced design

Vertical scaling is the pragmatic tool for stateful or legacy workloads that can't run as multiple copies — but it has a hard ceiling and a reboot in every step. Horizontal scaling is the cloud-native default: near-limitless, disruption-free, and it doubles as your availability strategy. When an architect says "design for scale-out," they're really saying "make the app stateless enough that instances are disposable."

Pairing with a load balancer

One loose end: five web VMs spread across three zones are useless if clients only know one VM's IP address. Scale-out designs are always deployed behind a load-balancing layer — an Azure Load Balancer for TCP/UDP traffic (layer 4) or an Application Gateway for HTTP-aware routing (layer 7) — which health-probes each instance and stops sending traffic to failed or rebooting ones. Scale sets integrate natively with both, registering and deregistering instances automatically as autoscale acts. How to choose, configure, and secure those load balancers is a networking-module story; for this module, remember the rule of thumb: no scale-out without a load balancer in front.

Key takeaways

  • Name the threat first: update domains handle planned maintenance, fault domains handle rack failure, availability zones handle datacenter loss.
  • Availability sets: up to 3 fault domains and 20 update domains, all within one datacenter — SLA ≥ 99.95% with 2+ VMs.
  • Availability zones are physically separate datacenters in a region — SLA ≥ 99.99% with 2+ VMs across 2+ zones; the modern default where supported.
  • A single VM earns ≥ 99.9% only when all disks are Premium SSD or Ultra.
  • VM Scale Sets add elasticity on top of availability; choose Flexible orchestration by default, Uniform for very large identical fleets (max ~1,000 instances; ≤ 100 per Uniform placement group).
  • Autoscale needs min/max/default plus paired rules with a dead band (e.g., out at 70% CPU, in at 30%) to avoid flapping; scale out aggressively, scale in cautiously.
  • Horizontal scaling is disruption-free and improves availability; vertical scaling reboots the VM and has a size ceiling.
  • No scale-out without a load balancer distributing traffic and health-probing instances.

Quick recall

Q: A rack loses power in a datacenter. Which construct limited your blast radius — fault domains or update domains? A: Fault domains: they separate VMs onto different racks with independent power and networking. Update domains only govern planned reboot waves.

Q: What SLA do two VMs in an availability set carry, and what do they carry when placed in two availability zones instead? A: ≥ 99.95% in an availability set; ≥ 99.99% across availability zones.

Q: When does a single VM qualify for the 99.9% SLA? A: Only when every attached disk (OS and data) is Premium SSD or Ultra Disk.

Q: You need a scale set that mixes two VM sizes and lets you manage each instance as a normal VM. Which orchestration mode? A: Flexible — it allows mixed sizes and exposes each instance as a full standard VM. Uniform stamps identical clones from one model.

Q: Your autoscale rules scale out at CPU > 60% and scale in at CPU < 55%. What goes wrong? A: Flapping — the thresholds are too close, so the set oscillates between adding and removing instances. Leave a wide dead band (e.g., 70/30) and use cooldowns.

Q: Which VM does the default scale-in policy remove first? A: After rebalancing across zones/fault domains, the instance with the highest instance ID — effectively the newest VM (policy can be changed to newest/oldest explicitly).

Coming up

You can now design resilient, self-scaling VM fleets — but if you built today's architecture by clicking through the portal, could you rebuild it identically tomorrow, in another region, under pressure? In Episode 5 — Infrastructure as Code: ARM Templates and Bicep, we turn everything you've deployed so far into declarative, versioned, reviewable code — and meet the deployment engine that sits underneath every Azure resource you've ever created.