> ## Documentation Index
> Fetch the complete documentation index at: https://autopilot.docs.xano.com/llms.txt
> Use this file to discover all available pages before exploring further.

# HPA Auto-Optimization

> Turnkey HPA tuning — Autopilot classifies every autoscaler, applies the one lever that fits, parks idle workloads, and leaves the majority that are already fine alone.

Horizontal Pod Autoscalers are usually set once and forgotten — a target and a min/max, then
left to drift as the workload changes. Autopilot makes them turnkey: it **observes** every
HPA, **classifies** what it needs, **acts** on the single right lever, **suggests** what only
an operator should apply, and **explains** every move — while leaving the majority that are
already fine **untouched**.

Grounded in a fleet analysis, roughly **73% of HPAs need nothing** — and Autopilot changes
nothing on those. It engages only where the math says it pays off.

<Note>
  Auto is **off by default** and opt-in per cluster (`PodResizePolicy.spec.hpaAuto.enabled`),
  with a per-HPA override in **both** directions (`ops-ai.io/hpa-auto: enabled|disabled`) so you
  can canary it on a few workloads or exempt a critical one. Any explicit operator setting
  always wins over Auto.
</Note>

## What Autopilot watches

Signals are measured against the **right-sized (natural) request** — not the oversized
template — using the CPU percentiles Autopilot already computes:

| Signal              | What it means                                                                                   | Classification    |
| ------------------- | ----------------------------------------------------------------------------------------------- | ----------------- |
| P95 near target     | P95 CPU ≥ 90% of the scale trigger — undersized, no headroom                                    | **Floor**         |
| Spikes above target | P95 is fine but peaks cross target — bursty, not undersized                                     | **Behavior**      |
| Thin data           | Confidence below 0.5 — warming up, use a safe damped default                                    | **Warming**       |
| Comfortably under   | Both well under target — leave the HPA alone                                                    | **No-op** (\~73%) |
| Not CPU-scaled      | A memory or custom-metric HPA — Auto's levers are CPU-based, so it's labeled and left untouched | **Inert**         |

## The levers — one per signal

The two CPU **sizing** levers are substitutes: a workload gets whichever fits, never both.

<CardGroup cols={2}>
  <Card title="Request Floor" icon="chart-line">
    An undersized workload gets a CPU request that keeps load a cushion below the scale
    trigger, so it stops tripping on a `Max`-spike artifact.

    `floor = P95 / (target% × 80%)`; only ever **raises**, capped at 2× so cost can't balloon.
  </Card>

  <Card title="Scale-Up Window" icon="gauge">
    A bursty workload gets a damped scale-up window so a short peak rides on headroom instead
    of provisioning replicas — escalating under sustained oscillation.

    The `Balanced` preset: 90s stabilization, +100%/min.
  </Card>

  <Card title="Right-size minReplicas" icon="sliders">
    An HPA pinned at an over-committed `minReplicas` has its floor safely **lowered** — but
    only when a sustained trough of demand (a low percentile over a 24h window) confirms it's
    genuinely idle — and **restored the instant demand returns**.
  </Card>

  <Card title="minReplicas floor" icon="shield">
    An enforced `ops-ai.io/min-replicas` floor is raised back every cycle if a kubectl/Helm
    redeploy drops a live `minReplicas` below it — deferring to idle, scheduled, and
    limit-overage writers.
  </Card>
</CardGroup>

### Operator-applied suggestions

Some changes are a judgment call, so Autopilot **recommends** them and lets you apply with one
click — it never writes them itself:

* **Right CPU target** — when an HPA's CPU target is set so high it can never scale (a disabled target), Auto surfaces a clickable "→ 70%" chip.
* **Scheduled scale** — when a workload has a recurring daily peak, Auto offers a pre-filled scheduled-scale window so you can pre-warm for the burst instead of paying the cold scale-up each day.

<Info>
  **Why did Auto act?** The workload card shows the reason behind every decision — the measured
  oscillation (churn) rate against its threshold, whether Auto is damping the scale-up window,
  and the min-lower hold state — so a change is trustable, never a mystery.
</Info>

## Idle Mode — park quiet workloads

Separately from Auto's tuning, **Idle Mode** auto-reduces a workload that has been genuinely
idle (P99 CPU below a threshold for a sustained duration) and restores it on wake. It's the
horizontal counterpart to right-sizing: instead of shrinking a request, it parks replicas
while nothing is happening.

* Opt-in via `PodResizePolicy.spec.idleMode.enabled`.
* Auto and Idle are independent and coexist — Auto tunes *how* the HPA scales while awake; Idle *parks* it while quiet. While a workload is actively idle, Auto's writes pause and resume on wake.
* The **Idle Workloads** dashboard page lists every parked workload with its savings, replica counts, and idle-since time.

## Companion: Scheduled Scaling

Auto handles the load it can't predict. [Scheduled Scaling](/platform/scheduled-scaling)
handles the bursts you **can** predict — a nightly job, a Monday-morning login spike, a sale —
by raising `minReplicas` during a defined window and restoring it after. The two coexist:
schedules guarantee capacity for known peaks, Auto keeps the HPA well-behaved the rest of the
time.

## Where to tune it

* **Scaling Policies** page → the PodResizePolicy Safety section has the cluster-wide **Auto** on/off toggle.
* **[HPA Audit](/platform/hpa-audit)** page → a fleet-wide view of every HPA with per-HPA Auto overrides and bulk tuning.
* **Workload detail** → the HPA card shows the live gauge, the resolved Auto decision, provenance, and per-HPA controls.

See the full mechanism walkthrough in [How Autopilot Works](/guides/how-it-works).
