Skip to content

Compute high availability on AWS

Availability at the compute tier comes from three things working together: instances that can be replaced without ceremony, something that notices when one is unhealthy, and something that stops sending traffic to it.

Prefer horizontal scaling. Adding instances spreads risk across more failure domains, keeps any single failure small, and can be done without downtime. Vertical scaling concentrates risk in one larger instance, requires a restart to change, and hits a hard ceiling at the largest instance size available.

The corollary is that instances must be disposable. Anything that makes a particular instance special — local state, a manual configuration step, a hostname something else depends on — converts a routine replacement into an incident.

An Auto Scaling group maintains a desired number of healthy instances across the Availability Zones you nominate. It replaces instances that fail their health checks, rebalances across zones, and adjusts capacity in response to demand. For availability purposes the scaling is almost secondary: the self-healing is the point. A group with a fixed desired capacity and no scaling policy still restores capacity after a failure, which a standalone instance does not.

Define the group from a launch template. Launch configurations are legacy — see Auto Scaling.

A load balancer distributes traffic across targets, checks their health, and removes unhealthy targets from rotation. Combined with an Auto Scaling group, an instance that starts failing is first taken out of service and then replaced, with no operator involved.

Enable cross-zone load balancing so that an imbalance in instance count between Availability Zones does not become an imbalance in load, and set the health check to test something that actually indicates the application is working — a route that touches the dependencies, not a static file that a half-broken process will happily still serve.

Every recovery path in a highly available design assumes the image it launches from is current. Keep AMIs patched and rebuilt on a schedule, version them, test them before they enter the launch template, and copy them to any Region where a recovery plan expects to launch from them. An AMI pipeline (EC2 Image Builder or equivalent) turns this from a task somebody remembers into a process.

Capacity is not guaranteed to be there when you need it. If a recovery plan depends on launching a specific instance type in a specific Availability Zone at short notice — precisely the moment when everyone else in that zone is doing the same thing — reserve it. On-Demand Capacity Reservations hold capacity explicitly; Reserved Instances and Savings Plans reduce cost but do not, on their own, reserve capacity unless the reservation is zonal.

Route 53 can monitor an endpoint over HTTP, HTTPS or TCP and stop returning it once it fails, which lets DNS act as the failover mechanism between two independent stacks — for example an on-premises web farm as primary and an AWS environment as secondary.

The mechanics: create a health check against the primary endpoint, create failover routing records with the primary and secondary targets, and let Route 53 switch when the check fails. No manual intervention is required, and the practical recovery time is the health-check interval plus the record’s TTL — which is why failover records normally carry a short TTL.

  1. Establish an AMI build and patch process before anything else, because everything below depends on it.
  2. Deploy across at least two, preferably three, Availability Zones.
  3. Front the instances with a load balancer and a meaningful health check.
  4. Put the instances in an Auto Scaling group defined by a launch template.
  5. Add Route 53 health checks and failover records where the failover is between stacks rather than within one.
  6. Rehearse the failover on a schedule, and monitor utilisation so the scaling thresholds stay sensible as the workload changes.