Course outline

6.1

Vertical vs Horizontal Scaling and High Availability

Scale up, scale out, and why "highly available" means at least two AZs.

16 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Tell scalability, elasticity, agility, high availability and fault tolerance apart, in one sentence each.
  • Explain vertical scaling (scale up/down) on EC2: how a resize works, why it causes downtime, where its ceiling is, and when it is still the right choice.
  • Explain horizontal scaling (scale out/in): why it needs a load balancer and stateless servers, and what to do with session state.
  • Design for high availability across at least two Availability Zones, active-active or with a passive standby, and find hidden single points of failure.
  • Work out how much capacity you need so the app survives losing one AZ (N+1 across AZs) with 2, 3 or more AZs.
  • Map exam keywords to the right answer: Auto Scaling group, Multi-AZ, load balancer or a bigger instance.

#Five words that sound alike

Chapter 6 is about two services, Elastic Load Balancing (ELB) and EC2 Auto Scaling. Both exist to deliver a handful of properties that exam questions name very precisely. Get the words straight first.

WordWhat it meansQuestion it answers
ScalabilityThe system can handle more load by adding resources, either bigger ones or more of them.“Can it grow?”
ElasticityThe system adds and removes resources automatically, following demand, so capacity tracks the load in both directions and you pay only for what you use.“Does it grow and shrink by itself?”
AgilityNew resources are available in minutes, not the weeks it takes to buy and rack hardware.“How fast can I get capacity?”
High availability (HA)The system keeps running when a component or a whole data centre fails, usually by running in at least two Availability Zones. A short blip during failover is accepted.“Does it survive a failure?”
Fault toleranceThe stricter form: the system keeps working with no interruption and no loss of capacity when something fails, because full spare capacity is already running.“Does a failure go unnoticed?”

Scalability is about load. High availability is about failure. They are linked, because both are usually built from several servers spread out, but a system can be one without the other: four servers in one AZ scale well and die together; one primary database with a standby in another AZ is highly available but cannot handle more load than the primary.

#Vertical scaling: a bigger instance

Vertical scaling (scale up, or scale down) means changing the size of one instance: more vCPUs, more memory, more network bandwidth. On EC2 you change the instance type, for example from t3.large (2 vCPU, 8 GiB) to r7i.4xlarge (16 vCPU, 128 GiB).

#How a resize works on EC2

  1. Stop the instance

    You can change the type of an EBS-backed instance only while it is stopped. From this moment the application is down. (Instance types and families were covered in lesson 4.1.)

  2. Change the instance type

    Pick a compatible type: same architecture (x86 or Arm), a supported AMI and drivers, and enough EBS attachments. The EBS volumes stay. Instance store data is lost on stop, and the public IPv4 address changes unless it is an Elastic IP.

  3. Start it again

    AWS places the instance on new hardware with the new size. Boot, application start-up and cache warm-up take minutes. Scaling down later is the same stop, change, start, with the same outage.

#The ceiling

Vertical scaling always ends somewhere. The range on EC2 is huge, but finite:

InstancevCPUMemory
Smallest general purposet2.nano / t3.nano1 / 20.5 GiB
The notes’ examplet2.micro → t2.large1 → 21 GiB → 8 GiB
Largest todayu7inh-32tb.480xlarge (High Memory)1,92032 TiB

The largest sizes exist for giant in-memory databases, cost a fortune, and are still one machine in one AZ. When demand outgrows them, there is nothing bigger to buy.

#When vertical scaling is the right choice

Fits vertical scalingWhy
Relational databases (RDS for MySQL or PostgreSQL, a self-managed database on EC2)One primary handles all writes; it cannot simply be copied ten times. More memory holds more of the working set in cache.
Caches such as ElastiCacheA bigger node holds more keys (ElastiCache also scales out with shards).
Legacy or single-instance softwareIt keeps state on local disk, holds a licence tied to one server, or was never written to run as several copies.
A quick fixNo code change; just a bigger box while you plan something better.

On RDS, changing the instance class is also a stop-and-start kind of change. With Multi-AZ turned on, RDS modifies the standby first and then fails over, which shrinks the outage to roughly a failover. Aurora Serverless v2 goes further and scales its capacity up and down in place, without a restart: vertical scaling made elastic. Both come back in the database chapters.

Scale up vs scale out

Vertical scaling swaps one server for a bigger one. Horizontal scaling adds more servers of the same size behind a load balancer.

Scenario

Regionus-east-1
Users
appt3.large · 8 GiBCPU 95%
Step 1 of 5
1

One t3.large (2 vCPU, 8 GiB) serves everyone. Traffic has grown and the CPU sits at 95%. The quick fix looks obvious: a bigger instance.

#Horizontal scaling: more instances

Horizontal scaling (scale out, or scale in) means changing the number of instances. Instead of one big server, run many identical ones and spread the work across them. This is how modern web applications grow, and the cloud makes it easy: an identical instance launches from the same launch template (lesson 4.3) in a minute or two.

It needs three things:

  1. A load balancer in front. Users cannot be given ten IP addresses. They get one name, and the load balancer sends each request to a healthy instance. On AWS that is ELB (lessons 6.2 to 6.4).
  2. Something that adds and removes instances. On AWS that is an Auto Scaling group (ASG) (lesson 6.5). It replaces failed instances too.
  3. Stateless servers. Any instance must be able to answer any request. If a server keeps the user’s session or uploaded files on itself, the next request landing on another server finds nothing, and scaling in throws the data away.

The fix for state is to move it out of the servers: sessions into ElastiCache or DynamoDB, files into S3 or EFS, data into a database. Once the web tier is stateless, adding the hundredth server is as easy as adding the second. (Sticky sessions are a shortcut with drawbacks, covered in lesson 6.4.)

Horizontal scaling has its own cost: the application must be built for it, and the shared pieces (database, cache) become the next thing that needs to scale.

#High availability: at least two AZs

An Availability Zone is one or more data centres with independent power, cooling and networking, a few kilometres from the other AZs of the Region and linked to them by fast, low-latency fibre (lesson 1.2). AZs rarely fail, but power, cooling, networking and human errors do happen. High availability on AWS means running the application in at least two AZs, so that losing one does not take it down.

#Active-active and passive standby

Active-activeActive-passive (standby)
How it worksEvery copy in every AZ serves traffic all the time.One copy serves; a standby in another AZ receives a copy of the data and waits.
When an AZ failsThe load balancer stops sending traffic to the dead AZ within seconds.The standby is promoted. RDS Multi-AZ (one standby) typically takes 60 to 120 seconds.
Extra capacity used day to dayYes, all copies do workNo, the standby is idle (a Multi-AZ standby cannot even serve reads)
Typical AWS examplesWeb and app tiers: ASG across AZs + ELBRDS Multi-AZ DB instance; Multi-AZ DB clusters and Aurora fail over faster (usually under 35 and about 30 seconds)

Both are highly available. Active-active goes hand in hand with horizontal scaling; passive standby is the usual answer for a database primary that cannot run as several writers.

#High availability is not the same as fault tolerance

A two-AZ web tier with two instances in each AZ is highly available: lose an AZ and it keeps running. But if each AZ was running at 60%, the two survivors now need 120% and users see slow pages until the Auto Scaling group launches more. A fault tolerant design keeps full capacity after the failure, which means running enough spare capacity all the time. The exam usually treats “fault tolerant” and “survive an AZ failure” as pointers to Multi-AZ, but when a question says “without any degradation” or “no performance impact”, it is asking you to size for the failure (next section).

#Single points of failure

A single point of failure (SPOF) is any one component whose failure stops the whole system. Multi-AZ only helps if every tier is multi-AZ. Typical hidden SPOFs:

  • All instances in one AZ, even with a load balancer in front.
  • A single-AZ database behind a perfectly multi-AZ web tier.
  • One NAT gateway in AZ a used by private subnets in every AZ (lesson 3.4): AZ a fails and the healthy AZ b instances lose internet access. Use one NAT gateway per AZ.
  • A single EC2 instance acting as a proxy, bastion or cron server that the app depends on.
  • An EBS volume (one AZ) or EFS One Zone holding shared data.

When an Availability Zone fails

An AZ is one or more data centres with its own power and network. AZs fail rarely, but they do fail, and the design decides whether users notice.

Scenario

Regionus-east-1
AZ a
Users
Load balancer
web-1
web-2
RDS primary
Step 1 of 3
1

Two web servers and the database, all in AZ a. It scales, and losing one server is survivable. It looks redundant.

#Sizing for an AZ failure: N+1 across AZs

If the application needs P instances at peak and runs in N AZs, then after losing one AZ only N − 1 AZs remain. To keep full capacity with no scaling during the failure (AWS calls this static stability), each AZ needs:

instances per AZ = P ÷ (N − 1), rounded up, and total = per AZ × N.

Peak needAZsPer AZTotal runningSpare over peakCapacity lost in an AZ failureCPU at peak, normal
1221224100%50%50%
12361850%33%67%
12441633%25%75%
12 (no N+1)34120%33%100%, then 150% after the failure

Two lessons hide in this table:

  • With 2 AZs, losing one costs half your capacity, so surviving it without degradation means doubling the fleet. With 3 AZs you lose a third and need only 50% extra. More AZs make the insurance cheaper, which is why production designs often use three.
  • Without spare capacity the survivors run past 100% until Auto Scaling launches replacements, which takes minutes and depends on capacity being available in the remaining AZs at the moment everyone else is also launching there.

A worked example. A shop needs 9 instances at peak and runs in 3 AZs. Each AZ needs 9 ÷ 2 = 4.5, so 5 instances, 15 in total. Normally each runs at 9 ÷ 15 = 60% at peak. If an AZ fails, 10 remain and run at 9 ÷ 10 = 90%: busy but serving everyone. Spreading the same 9 as 3 + 3 + 3 would leave 6 survivors at 150%.

The same reasoning is the old N+1 rule (one spare beyond what you need), applied to whole AZs instead of single servers.

Capacity left when an AZ fails

The app needs a fixed number of instances at peak. Choose how many AZs you spread over and how you size them, then fail AZ a and watch the survivors.

1. Number of AZs

2. Instances needed at peak

3. Sizing rule

4. AZ a

AZ a

CPU 50%

AZ b

CPU 50%

Per AZ

12

Provisioned

24

Spare over peak

100%

CPU at peak, all AZs up

50%

Capacity lost

0%

CPU at peak, AZ a down

–

Each AZ alone can carry the peak. The price is 12 extra instances (100% over peak). More AZs make that insurance cheaper.

Self-checkQuestion

An application needs 8 instances at peak. It must survive the loss of one Availability Zone with no degradation and no scaling activity during the failure. What is the smallest total number of instances to run if it uses three AZs?

#Elasticity: following the daily curve

Most applications have a daily rhythm: quiet at night, busy by day, a peak in the evening. Fixed capacity is either too much most of the time or too little at the peak. Resizing a single instance cannot follow the curve without outages. An Auto Scaling group with a scaling policy can, and that is what makes it elastic: you pay for roughly the capacity you use, and a bigger peak than expected is handled by launching more instances (up to the group’s maximum).

One day of traffic, four strategies

Dashed: instances the load needs each hour. Solid: instances running. The chips add up the day so far.

Scenario

Hour

00:00

Needed now / Running now

3 / 16

Instance-hours paid

0

Demand not served

0

048121600040812162024
runningneeded
Step 1 of 4
1

The classic data-centre answer: buy for the busiest hour of the year and run it all day. 16 instances, always.

#Where each one shows up on AWS

GoalAWS building blockWhere it is taught
Scale one EC2 instance up/downChange the instance type (stop, change, start)This lesson; instance types in 4.1
Scale out/in and replace failed instancesEC2 Auto Scaling group, spread over several AZsLesson 6.5
One entry point, spread traffic, health checks, route around a dead AZElastic Load Balancing: Application, Network, Gateway Load BalancerLessons 6.2 to 6.4
Database HARDS Multi-AZ (standby), Multi-AZ DB cluster, Aurora (storage across 3 AZs, replicas)Database chapters
Database read scalingRead replicas, Aurora replicasDatabase chapters
Database vertical scalingChange the DB instance class; Aurora Serverless v2Database chapters
HA with no AZ planning at allRegional managed services: S3, DynamoDB, EFS Regional, Lambda spread data or compute across AZs for youTheir own chapters

#What goes wrong

SymptomCauseFix
Site is down while “just upgrading the server”Vertical resize needs a stop/startResize during a window, or scale out instead; for RDS, Multi-AZ shortens it
Users randomly logged out after adding instancesSession kept in server memoryExternalise sessions (ElastiCache, DynamoDB), or sticky sessions as a stopgap
Whole app down in an AZ outage despite “multiple servers”All instances, or the database, in one AZASG across at least two AZs, RDS Multi-AZ
Healthy AZ b instances cannot reach the internet when AZ a failsSingle NAT gateway in AZ aOne NAT gateway per AZ, per-AZ route tables
Site survives an AZ outage but is painfully slowNo spare capacity: survivors over 100%Size each AZ for N − 1, or accept degradation knowingly
Instance you stopped to resize was terminatedIt belongs to an ASG, which treats a stopped instance as unhealthyChange the launch template and replace instances (instance refresh, lesson 6.5)
Bill stays high at nightCapacity sized for peak and never shrinksAuto Scaling with a scaling policy; scheduled scaling for known patterns

#How it is used in system design

  • Default shape of a web application on AWS: a load balancer across at least two (often three) AZs, an Auto Scaling group of stateless instances in those AZs, sessions in ElastiCache or DynamoDB, files in S3, and a Multi-AZ database. Every tier survives an AZ; the web tier also scales.
  • Scale the stateless tiers out, scale the stateful core up (and add read replicas or caching in front of it), until it is worth redesigning the data layer.
  • Pick the AZ count deliberately. Two AZs is the minimum for HA; three makes surviving an AZ cheaper and is common for production.
  • Write availability as a number. If the business asks for 99.99% (about 52 minutes a year), a single instance with minutes-long resizes cannot meet it; multi-AZ active-active can.

#Try it yourself

These commands use the AWS CLI with placeholder IDs. They create billable resources: clean up afterwards.

List the AZs your account can use in a Region (AZ names map to different physical zones per account; the zone ID is the same for everyone):

aws ec2 describe-availability-zones --region us-east-1 \
  --query "AvailabilityZones[].[ZoneName,ZoneId,State]" --output table

Scale up one instance: stop it, change the type, start it, and see the downtime yourself.

aws ec2 stop-instances --instance-ids i-0abc1234def567890
aws ec2 wait instance-stopped --instance-ids i-0abc1234def567890
aws ec2 modify-instance-attribute --instance-id i-0abc1234def567890 --instance-type Value=t3.large
aws ec2 start-instances --instance-ids i-0abc1234def567890
aws ec2 describe-instances --instance-ids i-0abc1234def567890 \
  --query "Reservations[].Instances[].[InstanceType,PublicIpAddress]"

Note that the public IP changed (unless it is an Elastic IP).

Scale out across two AZs (a preview of lesson 6.5): an Auto Scaling group from an existing launch template, with one subnet in each AZ.

aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name web-asg \
  --launch-template LaunchTemplateName=web-lt,Version='$Latest' \
  --min-size 2 --max-size 6 --desired-capacity 2 \
  --vpc-zone-identifier "subnet-0aaa1111bbbb2222c,subnet-0ddd3333eeee4444f"

# Watch it spread the two instances over both AZs
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names web-asg \
  --query "AutoScalingGroups[].Instances[].[InstanceId,AvailabilityZone,HealthStatus]"

# Scale out by hand, then back in
aws autoscaling set-desired-capacity --auto-scaling-group-name web-asg --desired-capacity 4
aws autoscaling set-desired-capacity --auto-scaling-group-name web-asg --desired-capacity 2

Clean up: aws autoscaling delete-auto-scaling-group --auto-scaling-group-name web-asg --force-delete.

Turn a single-AZ RDS instance into a highly available one (passive standby):

aws rds modify-db-instance --db-instance-identifier shop-db --multi-az --apply-immediately

#Summary

Key takeaways

  • Scalability handles more load; elasticity adds and removes capacity automatically with demand; agility gets resources in minutes; high availability survives failures; fault tolerance survives them with no visible impact.
  • Vertical scaling (up/down) = a bigger instance. Needs a stop/start on EC2 (downtime), hits a ceiling (today 32 TiB, 1,920 vCPUs), stays one machine in one AZ. Right for databases, caches and legacy apps.
  • Horizontal scaling (out/in) = more instances behind a load balancer, added and removed by an Auto Scaling group. Requires stateless servers; put sessions in ElastiCache or DynamoDB.
  • High availability = at least two AZs. Active-active (ASG + ELB) fails over in seconds; passive standby (RDS Multi-AZ) in about 1–2 minutes.
  • Find every single point of failure: one AZ, single-AZ database, one NAT gateway, one special server.
  • To survive an AZ with no degradation, run P ÷ (N − 1) per AZ: 2 AZs = 100% extra, 3 AZs = 50% extra.
  • Exam: stateless / web tier / spikes → ASG; survive a data centre / fault tolerant → Multi-AZ; database needs more memory → scale up.