Autoscaling Policies

Autoscaling policies dynamically adjust compute capacity in response to demand or resource signals so a service can maintain sufficient capacity. A good policy balances responsiveness, availability, cost, and stability rather than simply maximizing resource usage.

An autoscaling policy defines when capacity should increase or decrease and by how much. Common signals include CPU utilization, memory utilization, request rate, queue depth, latency, or application-specific metrics. The policy normally operates within configured minimum and maximum capacity limits.

Scale-out adds capacity when demand rises or the service approaches a defined threshold. Scale-in removes capacity when demand falls. In distributed systems, the policy should account for startup time because newly created instances may not become useful immediately.

Thresholds alone can cause oscillation: a service may scale out, observe lower utilization, scale back in, and then repeat the cycle. Cooldowns, stabilization windows, hysteresis, and conservative scale-in rules can reduce this behavior.

For a Java backend, autoscaling is usually an infrastructure concern rather than something implemented inside application code. The application should instead expose useful health and workload metrics, remain stateless where practical, and tolerate instances being added or removed.

Capacity planning still matters even with autoscaling. Minimum capacity must cover baseline demand, maximum capacity must cover expected bursts, and scaling limits should be tested against dependencies such as databases, connection pools, caches, and downstream services.

Key points

Interview questions

What is an autoscaling policy, and why would you use one?

An autoscaling policy defines how infrastructure capacity changes according to workload or resource signals. It can add instances when demand increases and remove them when demand decreases. The goal is to maintain service capacity without permanently provisioning for the largest expected workload. The policy normally includes boundaries so scaling remains controlled.

Why can a CPU-based autoscaling policy be insufficient for a backend service?

CPU utilization is useful when CPU consumption tracks workload, but it is not always the bottleneck. A service can have low CPU while requests are waiting on a database, external API, lock, or connection pool. Conversely, background processing can produce high CPU without increased user traffic. Choosing a signal therefore requires understanding the application's actual capacity constraint.

How would you prevent autoscaling from oscillating between scale-out and scale-in?

I would avoid making scale-in react immediately to a short-lived decrease in load. Stabilization windows or cooldown periods can require the signal to remain below a threshold before removing capacity. Hysteresis can also use different scale-out and scale-in thresholds. I would additionally consider the startup and shutdown characteristics of the workload.

How can autoscaling overload a database even when the application tier is scaling correctly?

Adding application instances can multiply concurrent database connections, queries, and transaction load. If the database has a fixed throughput or connection limit, application autoscaling can move the bottleneck downstream rather than solving it. I would therefore model dependency capacity and control connection pools and concurrency. Database saturation should also be considered when defining the application's maximum scale.

What factors would you consider when designing an autoscaling policy for a Java backend?

I would identify the real workload signal, establish minimum and maximum capacity, and account for JVM startup and warm-up behavior. I would choose scaling and stabilization parameters based on observed latency and traffic patterns rather than arbitrary thresholds. I would also examine downstream limits such as database connections, caches, and external services. Finally, I would load-test the policy to verify that it responds to bursts without creating instability or excessive cost.