Autoscaling Explained: Horizontal, Vertical, and the Metrics That Drive It

Autoscaling is the process of dynamically allocating computational resources to an application based on its current load. Instead of provisioning for peak capacity, which is wasteful, or average capacity, which risks failure during traffic spikes, autoscaling aims to continuously match resources to demand. This practice is a cornerstone of modern cloud computing, enabling both cost efficiency and high availability. It's the mechanism that delivers on the promise of rapid elasticity[1], one of the five essential characteristics of cloud computing defined by the U.S. National Institute of Standards and Technology (NIST).

At its heart, autoscaling is a feedback loop that balances performance against cost. It decides when to add or remove resources like virtual machine instances, containers, or CPU cores to maintain a target performance level, such as keeping average response time below 200 milliseconds or CPU utilization below 75%. Understanding how this loop works, its different forms, and its inherent tradeoffs is critical for designing and operating resilient, cost-effective systems.

The Core Mechanism: A Closed-Loop Control System

Autoscaling is a practical application of a control system[2], a concept from engineering and mathematics that describes a system designed to regulate other devices or systems. This process operates in a continuous, closed loop with four distinct stages.

Step 1: Monitoring and Metrics Collection

The system cannot scale what it cannot measure. The first step is collecting performance metrics from the application and its underlying infrastructure. These metrics are time-series data points that represent the health and load of the system. Common metrics include:

  • CPU Utilization: The percentage of CPU time being used.
  • Memory Usage: The amount of RAM consumed.
  • Network I/O: The rate of data entering and leaving the instances.
  • Request Count or Rate: The number of incoming requests per second.
  • Queue Length: The number of pending messages in a queue (e.g., RabbitMQ, SQS), which is a strong indicator of back-pressure.

This data is collected by monitoring agents and aggregated in a centralized service. In cloud environments, these are services like Amazon CloudWatch[3], Google Cloud Monitoring[4], or Azure Monitor. In containerized environments, Prometheus[5] is a widely adopted open-source standard for metrics collection.

Step 2: Evaluation and Decision

The autoscaler, which is a controller process, periodically evaluates the collected metrics against predefined rules or policies. This policy defines the desired state of the system. For example, a simple policy might be: "Maintain average CPU utilization across all instances at 60%."

If the current metric value (e.g., 85% CPU) deviates from the target (60% CPU), the controller calculates the necessary adjustment. If the current value is above the target, it decides to scale up. If it's significantly below, it decides to scale down to save costs. The logic is typically straightforward arithmetic to determine how many new instances are needed to bring the average back to the target.

Step 3: Actuation

Once a decision is made, the controller executes it by interacting with the infrastructure's control plane.

  • For a scale-up event, it might make an API call to a cloud provider to launch one or more new virtual machine instances from a pre-configured template or launch a new pod in a Kubernetes cluster.
  • For a scale-down event, it will select one or more instances or pods to terminate. Termination policies are important here; for example, the system might choose to terminate the oldest instance or the one with the fewest active connections to minimize disruption.

Step 4: Cooldown and Stabilization

After a scaling event, there is a cooldown period. During this time, the autoscaler will not initiate another scaling activity. This is crucial for system stability. Without a cooldown, the system could suffer from "thrashing":

  1. Load increases, triggering a scale-up.
  2. The new instances start, but take time to become fully operational and accept traffic.
  3. Before the new instances' effect is reflected in the metrics, the controller might see the load is still high and trigger another scale-up.
  4. Eventually, too much capacity is added. The load drops sharply, triggering a scale-down, and the cycle repeats.

Cooldown periods, typically lasting from a few to several minutes, allow the system to stabilize and the metrics to reflect the impact of the last scaling action before another decision is made.

Two Dimensions of Scaling: Horizontal and Vertical

Autoscaling can be implemented along two different axes. The choice between them depends heavily on the application's architecture.

Horizontal Scaling (Scaling Out)

Horizontal scaling means adding more machines to your pool of resources. If you have two web servers, scaling horizontally means adding a third, fourth, or fifth server. This approach is intrinsically linked with load balancing, which distributes incoming traffic across the entire pool of servers. Each server in the pool is typically identical.

This model was popularized by web-scale companies in the early 2000s and became a foundational pattern for cloud computing with services like Amazon EC2 Auto Scaling[6], first launched in 2009. It's ideal for stateless applications, where any server can handle any request because no session-specific data is stored locally. If a server fails, the load balancer simply redirects its traffic to the remaining healthy servers, providing high availability.

Advantages:

  • High Availability: The failure of a single instance does not bring down the application.
  • Near-Infinite Scalability: You can theoretically add as many instances as your cloud provider or budget allows.

Disadvantages:

  • Application Design Constraints: It only works for applications designed to be distributed. Stateful applications, like a primary relational database, cannot be scaled this way without significant architectural work (e.g., sharding, read replicas).
  • Increased Complexity: Managing a fleet of servers, even with automation, introduces complexity in networking, service discovery, and configuration management.

Vertical Scaling (Scaling Up)

Vertical scaling means increasing the resources of a single machine, for example, moving from a virtual machine with 2 vCPUs and 4 GB of RAM to one with 4 vCPUs and 8 GB of RAM. This is like upgrading the engine in a car rather than buying a second car.

This approach is simpler for applications that were not designed for a distributed environment. For a monolithic application or a traditional database server, vertical scaling is often the most direct path to improving performance. However, it has fundamental limits.

Advantages:

  • Simplicity: No changes are needed to the application's architecture. It remains a single unit.
  • Lower Management Overhead: There is only one machine to manage, monitor, and secure.

Disadvantages:

  • Finite Limits: You can only scale up to the largest instance size offered by your provider. This creates a hard ceiling on performance.
  • Downtime: Most vertical scaling operations require the instance to be stopped, resized, and restarted, resulting in downtime. While some providers offer features like hot-add CPU, this is not universally available or applicable to all resources.
  • Single Point of Failure: If the single, powerful machine fails, the entire application goes down.
  • Cost: The cost of the largest machine types can be disproportionately high compared to their smaller counterparts.

A Concrete Example: Kubernetes Horizontal Pod Autoscaler

In the world of container orchestration, Kubernetes[7] provides a built-in controller for horizontal scaling called the Horizontal Pod Autoscaler (HPA). The HPA automatically scales the number of pods in a ReplicaSet, Deployment, or StatefulSet based on observed metrics.

The HPA gets its metrics from the Kubernetes Metrics API[8], which is typically provided by an add-on called the Metrics Server. Here is a YAML manifest for a basic HPA that targets a deployment named my-app:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
 name: my-app-hpa
spec:
 scaleTargetRef:
 apiVersion: apps/v1
 kind: Deployment
 name: my-app
 minReplicas: 2
 maxReplicas: 10
 metrics:
 - type: Resource
 resource:
 name: cpu
 target:
 type: Utilization
 averageUtilization: 80

Let's break this down:

  • scaleTargetRef: This tells the HPA which workload to scale. Here, it's the my-app deployment.
  • minReplicas: 2: The HPA will ensure there are always at least 2 pods running.
  • maxReplicas: 10: The HPA will not scale beyond 10 pods.
  • metrics: This section defines the scaling policy. Here, we're using a single metric: CPU. The target is set to an averageUtilization of 80%. This means the HPA will try to keep the average CPU usage across all pods at 80% of their requested CPU resources.

According to the official Kubernetes documentation[9], the HPA controller uses the following formula to determine the desired number of replicas:

desiredReplicas = ceil[currentReplicas * (currentMetricValue / desiredMetricValue)]

If currentReplicas is 3, the desiredMetricValue (target) is 80, and the currentMetricValue is 120, the calculation would be:

desiredReplicas = ceil[3 * (120 / 80)] = ceil[3 * 1.5] = ceil[4.5] = 5

The HPA would scale the deployment from 3 to 5 pods.

Beyond Reaction: Predictive and Scheduled Scaling

Reactive autoscaling, as described above, has a built-in delay. The system must first experience high load before it can react. Two other models, scheduled and predictive scaling, address this by being proactive.

Scheduled Scaling

If your application experiences highly predictable traffic patterns, you can use scheduled scaling. For example, a business application might see a surge in traffic every weekday at 9:00 AM and a drop-off at 6:00 PM. A scheduled scaling policy[10] can be configured to proactively increase the minimum number of instances just before the surge and decrease them after traffic subsides. This is simple, reliable, and avoids the lag of reactive scaling for known cycles.

Predictive Scaling

Predictive scaling uses machine learning models to forecast future load based on historical data. Services like AWS Auto Scaling with predictive scaling[11] analyze historical metrics (e.g., from the last 14 days) to identify daily and weekly patterns. It then generates a forecast for the next 48 hours and creates scheduled scaling actions to match the predicted demand. This offers the proactivity of scheduled scaling without requiring manual analysis and configuration, and it can capture more complex patterns. It's a powerful tool for workloads with regular, cyclical demand that isn't a simple on/off pattern.

The Decision Lens: Tradeoffs and Failure Modes

Autoscaling is powerful, but it's not a panacea. A technical leader must weigh its benefits against its complexity and potential pitfalls.

Use autoscaling when:

  • Your application has a variable or unpredictable workload.
  • Cost optimization for idle resources is a priority.
  • High availability and performance under load are non-negotiable.
  • Your architecture is composed of stateless services that can be easily added or removed.

Be cautious or reconsider when:

  • Your application is stateful. A traditional relational database like PostgreSQL or MySQL is hard to scale horizontally. While you can use vertical scaling, or more complex architectures like read replicas or managed distributed databases (Amazon Aurora[12], Google Cloud Spanner[13]), you cannot simply add another primary database instance to an autoscaling group.
  • Your application has long startup times. If a new instance takes 10 minutes to become healthy (e.g., initializing, warming up a large cache), reactive autoscaling will always be too slow to handle a sudden traffic spike. By the time new capacity comes online, your existing instances may already be overwhelmed. In these cases, you must overprovision or rely on predictive/scheduled scaling.
  • Your workload is constant and predictable. If traffic is flat 24/7, the complexity of autoscaling is unnecessary. It's simpler and more reliable to provision a fixed number of instances to handle the known load.

Common Failure Modes and Costs

  • Dependency Bottlenecks: Autoscaling your web tier is useless if it just shifts the bottleneck to your database, a third-party API, or a message queue. A holistic view of the system is required. Scaling one component often reveals the next bottleneck in the chain.
  • Metric Lag and Configuration Errors: A delay in metrics reporting can slow down scaling reactions. A poorly chosen metric (e.g., memory usage in a Java application, which often allocates a large heap upfront) can lead to nonsensical scaling behavior. A misconfigured cooldown period can lead to thrashing.
  • Runaway Costs: A bug in a new code deployment could cause a memory leak or an infinite loop, maxing out CPU. A reactive autoscaler will interpret this as high load and scale up to the maximum limit, potentially running hundreds of expensive instances to service zero real traffic. Strict budget alerts and sensible maxReplicas settings are essential guardrails.
  • Cold Starts: In serverless computing (AWS Lambda[14], Google Cloud Functions[15]), scaling from zero to one involves a "cold start," which is the time it takes to provision the execution environment and initialize your code. This can add hundreds of milliseconds or even seconds of latency to the first request. While platforms have improved, cold start latency[16] remains a key consideration for latency-sensitive serverless applications.

Correcting Common Misconceptions

Misconception 1: "Autoscaling is just for saving money."
It's equally about maintaining performance and availability. Under-provisioning during a spike can lead to lost revenue, frustrated users, and SLA penalties that far exceed the cost of the extra compute resources. Autoscaling's primary job is to ensure the right amount of capacity is available at all times.

Misconception 2: "You just turn it on and it works."
A default autoscaling configuration is rarely optimal. It requires careful tuning of metrics, thresholds, instance types, and cooldown periods based on the specific behavior of your application. A poorly configured autoscaler can be more dangerous than no autoscaler at all.

Misconception 3: "Horizontal scaling is always better."
Vertical scaling is often the right choice for stateful workloads or monolithic applications where re-architecting for horizontal scaling is infeasible or not cost-effective. The best approach is dictated by the application architecture, not by a universal rule.

Misconception 4: "Autoscaling eliminates the need for capacity planning."
It changes the nature of capacity planning but does not eliminate it. You still need to choose appropriate instance types, understand your application's resource footprint, and set sensible minimum and maximum scaling boundaries. Predictive scaling is, in essence, a form of automated, continuous capacity planning.

The State of Autoscaling Today

Autoscaling is a mature and broadly adopted technology. The patterns and practices are well-established across the industry.

  • Cloud Providers: All major clouds have robust, feature-rich autoscaling services at the core of their IaaS offerings, including Azure Virtual Machine Scale Sets[17], Google Compute Engine Autoscaler[18], and AWS EC2 Auto Scaling.
  • Container Orchestration: Kubernetes has become the standard for container management. Its built-in autoscaling primitives are a primary reason for its popularity. Beyond the HPA, the ecosystem includes the Vertical Pod Autoscaler (VPA)[19] for managing pod resource requests and limits, and the Cluster Autoscaler[20], which adds or removes underlying nodes (virtual machines) from the cluster itself.
  • Event-Driven Scaling: A significant trend is scaling based on application-level events, not just infrastructure metrics. For example, scaling a fleet of video processing workers based on the number of videos in a processing queue. Projects like KEDA (Kubernetes Event-driven Autoscaling)[21], a Cloud Native Computing Foundation (CNCF)[22] project, have emerged to standardize this pattern. KEDA integrates with dozens of event sources like Kafka, RabbitMQ, and cloud queues, allowing for fine-grained, event-driven scaling logic.
  • Serverless Abstraction: Serverless platforms represent the ultimate expression of autoscaling by making it completely transparent to the developer. The platform itself handles scaling from zero to thousands of concurrent executions and back down again, entirely managed by the provider. The developer focuses only on the code, not the infrastructure that runs it.
Sources (22)
  1. NIST Definition of Cloud Computing
  2. Control System - Wikipedia
  3. Amazon CloudWatch
  4. Google Cloud Monitoring
  5. Prometheus
  6. Amazon EC2 Auto Scaling
  7. Kubernetes
  8. Kubernetes Metrics API
  9. Kubernetes HPA Algorithm Details
  10. AWS Scheduled Scaling
  11. AWS Predictive Scaling
  12. Amazon Aurora
  13. Google Cloud Spanner
  14. AWS Lambda
  15. Google Cloud Functions
  16. AWS Lambda Execution Context (Cold Starts)
  17. Azure Virtual Machine Scale Sets
  18. Google Compute Engine Autoscaler
  19. Kubernetes Vertical Pod Autoscaler
  20. Kubernetes Cluster Autoscaler
  21. KEDA (Kubernetes Event-driven Autoscaling)
  22. Cloud Native Computing Foundation (CNCF)