Skip to main content
RunBook Academy

KubernetesLXXXII · Horizontal Pod AutoscalerHorizontal Pod Autoscaler

Behavior block — stabilization and scaling policies

Advanced⏱ ~13 minkubectl

What you'll learn

  • Configure the HPA behavior block
  • Set the stabilization window
  • Configure the scaling policies
  • Avoid thrashing and flapping

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The HPA behavior block controls the scaling behavior: the stabilization window prevents flapping, and the scaling policies limit the rate of scale-up and scale-down. This lesson walks the behavior block, the stabilization window, and the scaling policies.

The behavior block

The behavior block is part of the HPA configuration:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 3
  maxReplicas: 30
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 4
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30
      - type: Pods
        value: 4
        periodSeconds: 30
      selectPolicy: Max

The stabilization window

The stabilization window is the time the HPA looks back to determine the desired replica count:

scaleDown:
  stabilizationWindowSeconds: 300

The default for scale-down is 300 seconds (5 minutes). The HPA looks at the last 5 minutes of metrics; the highest desired replica count is selected.

gantt
    title Stabilization window (scale-down)
    dateFormat  YYYY-MM-DD
    section History
    Last 5 minutes of metrics :done, 2026-08-16, 5m
    section Decision
    Take the highest desired replica count :crit, 2026-08-16, 5m

The stabilization window prevents a brief spike from causing a scale-down.

For scale-up, the default is 0 seconds (immediate). The HPA scales up immediately when the metric exceeds the target.

The default behaviour

An HPA with no behavior block behaves as if it carried this one:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
    - type: Pods
      value: 4
      periodSeconds: 15
    selectPolicy: Max

Read it carefully, because it is not what most operators assume. The default asymmetry lives entirely in the stabilisation window: scale-up acts on the current recommendation, scale-down waits 300 seconds and then acts on the highest recommendation seen in that window. The rate policies are the same in both directions — 100% of the current replicas per 15 seconds — with an extra 4-Pods-per-15s policy and selectPolicy: Max on the way up. Once the window expires, the default scale-down can take the workload straight to minReplicas in a single step.

The scaling policies

The scaling policies limit the rate of scale-up and scale-down:

scaleUp:
  policies:
  - type: Percent
    value: 100
    periodSeconds: 30
  - type: Pods
    value: 4
    periodSeconds: 30
  selectPolicy: Max

The policies:

  • Percent: scale up by N% of current replicas per period.
  • Pods: scale up by N pods per period.
  • selectPolicy: Max: the larger of the two policies is used.

The example:

  • 100% of current replicas per 30s (e.g., 5 → 10 in 30s).
  • 4 pods per 30s.

The Max selectPolicy means the HPA uses the larger limit. The HPA can double the replicas in 30 seconds. Note the periodSeconds: the example uses 30, while the default is 15.

Tuning the scale-down policies

The default scale-down policy is not conservative — it allows the whole replica set to be removed in one 15 second period. A workload that must shed capacity gradually needs the policy written out:

scaleDown:
  policies:
  - type: Percent
    value: 10
    periodSeconds: 60
  - type: Pods
    value: 1
    periodSeconds: 60
  selectPolicy: Min

The example:

  • 10% of current replicas per 60s (e.g., 10 → 9 in 60s).
  • 1 pod per 60s.

The Min selectPolicy means the HPA uses the smaller limit. At 10 replicas both policies work out to 1 Pod, so this HPA scales down by one Pod per minute.

The asymmetry

The asymmetry that ships with the HPA is a matter of timing, not rate:

flowchart LR
    A[Default scale-up] --> B[No stabilisation window]
    B --> C["100% per 15s, or 4 Pods per 15s, Max"]
    D[Default scale-down] --> E[300s stabilisation window]
    E --> F["Then 100% per 15s"]
    G[Tuned scale-down] --> H[300s window]
    H --> I["Then 10% per 60s, or 1 Pod per 60s, Min"]

Scale-up reacts to demand immediately. Scale-down waits five minutes and takes the highest recommendation from that window, which is what prevents a transient dip from shrinking the workload. What the default does not do is make the descent gradual — that is the tuning shown above.

The stabilization window defaults

The default stabilization window:

DirectionWindow
scaleUp0s (immediate)
scaleDown300s (5 minutes)

The asymmetry is the default. The operator can override the windows.

The flapping

Flapping is the rapid scale-up and scale-down:

T+0:    CPU 80% → scale up to 5
T+30s:  CPU 50% → scale down to 4
T+60s:  CPU 80% → scale up to 5
T+90s:  CPU 50% → scale down to 4

The flapping is caused by short-term oscillations. The stabilization window prevents flapping:

T+0:    CPU 80% → desired replicas 5
T+30s:  CPU 50% → desired replicas 4
T+60s:  CPU 80% → desired replicas 5

Without stabilization: replicas oscillate 4-5
With stabilization (5m): HPA uses the max desired replicas (5)

The stabilization window looks at the history; the highest desired replica count is selected.

A tuned behavior block

Putting the tuning together — the defaults kept for the windows, an explicit conservative descent added:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60
    - type: Pods
      value: 1
      periodSeconds: 60
    selectPolicy: Min
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 30
    - type: Pods
      value: 4
      periodSeconds: 30
    selectPolicy: Max

The behavior is per-HPA. Different workloads may have different behaviors.

Cross-course references

  • The Helm course covers chart values for HPA behavior.
  • The Observability course covers HPA metrics.
  • The KEDA course covers advanced scaling behaviors.

Quiz

Knowledge check · 4 questions

  1. Q1. What is the default stabilizationWindowSeconds for scale-down?

  2. Q2. The HPA's default scaling behavior is asymmetric: scale-up is fast, scale-down is slow.

  3. Q3. Walk the configuration of the HPA behavior block for a production workload.

    Deployment nginx. The workload is critical (e.g., payment processing). The team is configuring the HPA to scale conservatively (fast scale-up, slow scale-down).

  4. Q4. What is HPA flapping, and how is it prevented?

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Configure the behavior block. The default delays a scale-down by five minutes but does not slow it down; tune for the workload.
  • Set the scale-up policies. Aggressive (e.g., 100% per 30s).
  • Set the scale-down policies. Conservative (e.g., 1 pod per 60s).
  • Set the stabilization window. 5 minutes for scale-down.
  • Test the behavior. Generate load; verify the scaling.
  • Document the behavior. The policies, the window, the rationale.

The behavior block is the HPA’s production tuning. Operating it well is configuring the policies and the window per workload.