> ## 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.

# How Autopilot Works

> One loop, every layer — how Autopilot provisions the right nodes, tunes every autoscaler, resizes pods in place, and consolidates safely.

**Your cluster right-sizes itself.** Autopilot continuously provisions the right nodes,
tunes every autoscaler, and resizes pods in place — cutting spend without a single restart
or a line of manual tuning. It changes only what needs changing, and proves every move safe
before it makes it.

<CardGroup cols={3}>
  <Card title="No restarts" icon="circle-check" />

  <Card title="No manual tuning" icon="circle-check" />

  <Card title="Every move reversible" icon="circle-check" />
</CardGroup>

Autopilot runs one continuous **observe → act** loop across four systems — node
provisioning, HPA tuning, right-sizing, and consolidation — acting only where it pays off.

<CardGroup cols={2}>
  <Card title="Provision" icon="server" href="#node-provisioning">
    The smallest node that fits the pending work.
  </Card>

  <Card title="Tune HPAs" icon="sliders" href="#hpa-auto-optimization">
    One lever per signal — and it leaves the \~73% that need nothing alone.
  </Card>

  <Card title="Right-size" icon="maximize" href="#cpu-memory-right-sizing">
    CPU and memory requests, in place, no restart.
  </Card>

  <Card title="Consolidate" icon="layer-group" href="#maintenance-consolidation">
    Bin-pack onto fewer nodes and drain the empties safely.
  </Card>
</CardGroup>

***

## Node Provisioning

When pods can't fit, Autopilot provisions the smallest right-sized VM for the job — not a
fixed pool size.

<Steps>
  <Step title="Pending Need">
    Unschedulable pods trigger a new node.

    **How:** Capacity-based — bootstrapping nodes are credited against pending demand so
    Autopilot doesn't over-provision.
  </Step>

  <Step title="Series & Size">
    Autopilot picks the machine series and size that fits the pending pods.

    **How:** Bin-packed against a per-cloud machine catalog (GKE/EKS), honoring min/max CPU
    & memory and `allowedMachineTypes`.
  </Step>

  <Step title="Zone Placement">
    Nodes land in zones that satisfy the pods' constraints.

    **How:** Zone-aware — respects PV zones + `zoneStrategy` (Primary/Balanced).
  </Step>

  <Step title="Warm Buffer (optional)">
    Keep N ready, empty nodes so bursts schedule instantly.

    **How:** `warmPoolSize` on-demand-only spares; reserved within `maxNodes`; off by default.
  </Step>

  <Step title="Right-Sized Node">
    The result: the cheapest node that fits, ready in minutes.

    **How:** Cold boot 5–11 min GKE / \~2–3 min EKS; a warm buffer makes it instant.
  </Step>
</Steps>

<Info>
  Unlike a fixed node pool, every node is provisioned to fit the actual pending work — no
  rounding up to a one-size pool.
</Info>

See the full details in [Node Scaling](/platform/node-scaling).

***

## HPA Auto Optimization

Autopilot makes horizontal autoscaling turnkey. Auto **observes** each HPA, **classifies**
what it needs (including the ones it won't touch), **acts** on the one right lever,
**suggests** what only an operator should apply, and **explains** every move — leaving the
\~73% that need nothing alone.

### What Autopilot watches

Signals are measured against the right-sized (natural) request, not the oversized template —
using the 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 (\~73% of the fleet).                                                                    | No-op          |
| **Not CPU-scaled**      | A memory or custom-metric HPA. Auto's levers are all CPU-based, so it labels the workload "scales on memory" and leaves it untouched. | Inert          |

### Acts — one lever per signal

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

<CardGroup cols={1}>
  <Card title="Request Floor (FLOOR)" icon="chart-line">
    Undersized workloads get a CPU request that keeps load a cushion below the scale trigger.

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

  <Card title="Scale-Up Window (BEHAVIOR / WARMING)" icon="gauge">
    Spiky workloads get a damped scale-up window so a short peak rides on headroom instead of
    adding replicas.

    **How:** Balanced preset — 90s stabilization, +100%/min.
  </Card>

  <Card title="Right-Size minReplicas" icon="sliders">
    An HPA pinned at an over-committed min gets its floor safely lowered — but only when a
    **24-hour trough** of demand says it's genuinely idle, not just quiet for a moment — and
    restored the instant demand returns. When a workload looks under-floored, the card
    surfaces a raise *suggestion* for review — advisory only, not auto-applied.

    **How:** The lower reads a low percentile (default P10) of the needed replicas over a
    configurable window (default 24h) — a sustained trough, so a brief lull can't trigger it
    — then +25% headroom, never below `max(2, operator floor)`, a PodDisruptionBudget's
    `minAvailable`, or a per-namespace change budget. Until \~3h of history builds it falls
    back to the live reading. It defers to idle/scheduled/limit-overage writers. On passive
    namespaces it's preview-only ("Auto would set min → N") without touching the HPA.
  </Card>
</CardGroup>

### Suggests — you apply

Operator-applied recommendations, never auto-written.

<CardGroup cols={2}>
  <Card title="Right CPU target" icon="crosshairs">
    When an HPA's CPU target is set so high it can never scale (a disabled target), Auto
    surfaces a clickable "→ 70%" chip. One click sets a sane target.
  </Card>

  <Card title="Scheduled scale" icon="calendar">
    When a workload has a recurring daily peak, Auto offers a pre-filled "Set up scheduled
    scale" window so you can pre-warm for the burst instead of paying the cold scale-up each
    day.
  </Card>
</CardGroup>

<Info>
  **Why did Auto act?** The workload card shows the reason behind every decision — the
  measured 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. Any explicit operator
  setting always wins over Auto.
</Info>

### Companion: Scheduled Scales

Auto handles load it can't predict. Scheduled Scales handle the bursts you **can** predict —
a nightly job, a Monday-morning login spike, a sale.

<Steps>
  <Step title="Define a window">
    Pick the days/times a workload needs more floor.

    **How:** Per-workload `ScheduledScalePolicy`; timezone-aware recurring windows.
  </Step>

  <Step title="Raise the floor on schedule">
    During the window, `minReplicas` is lifted so capacity is already there when the burst
    hits.

    **How:** Overrides the HPA's `minReplicas` for the window; each window can also set its
    own scale-up/down responsiveness.
  </Step>

  <Step title="Restore automatically">
    When the window ends, the original `minReplicas` and behavior are restored.

    **How:** Snapshots and restores the customer's original — hands off cleanly to Auto/base
    sensitivity.
  </Step>
</Steps>

Scheduled Scales and Auto coexist — schedules guarantee capacity for known peaks; Auto keeps
the HPA well-behaved the rest of the time. See
[Scheduled Scaling](/platform/scheduled-scaling) and
[HPA Behavior Overrides](/platform/scheduled-scale-behavior).

***

## CPU & Memory Right-Sizing

Autopilot continuously right-sizes every workload's CPU and memory requests from real usage.

<Check>
  **No restart, no downtime.** Autopilot applies every resize in place (Kubernetes in-place
  resize, KEP-1287) — your workloads shrink to fit real usage while they keep serving traffic.
</Check>

An illustrative before/after for one over-provisioned workload:

| Resource       | Before | After Autopilot   | Actual usage |
| -------------- | ------ | ----------------- | ------------ |
| CPU request    | 2000m  | **400m** (≈ −80%) | \~360m       |
| Memory request | 4Gi    | **2.3Gi**         | \~1.2Gi      |

The "After" reservation is sized to **P95-of-peaks + buffer** — right above real usage, not
rounded up to the original request.

**Stability guardrails** keep recommendations from churning:

<CardGroup cols={2}>
  <Card title="Hysteresis" icon="rotate-ccw">
    Holds the previous value when a rounded recommendation bounces between two buckets.
  </Card>

  <Card title="Circuit breaker" icon="shield">
    Reverts (then escalates) a downscale that correlates with a crash-loop.
  </Card>

  <Card title="HPA floor" icon="bar-chart">
    Keeps a CPU request floor when an HPA-managed workload has no replica headroom.
  </Card>

  <Card title="Downscale delay" icon="clock">
    Blocks CPU downscales for an adaptive delay after a change; upscales are immediate.
  </Card>
</CardGroup>

See the full algorithm in [Pod Resizing](/platform/pod-resizing).

***

## Maintenance & Consolidation

During maintenance windows, Autopilot bin-packs workloads onto fewer nodes and safely drains
the empties — cutting cost without ever causing an outage.

### Standard drain vs Autopilot consolidation

<CardGroup cols={2}>
  <Card title="Standard drain" icon="triangle-alert">
    * Cordons the node and evicts everything at once — a thundering herd.
    * No check that evicted pods will fit anywhere — they can go Pending.
    * Ignores whether replacements come back healthy before moving on.
    * One node at a time by hand, or a script that cordons many at once and floods the scheduler.
    * No rollback — if it goes wrong, the pods are already gone.
  </Card>

  <Card title="Autopilot consolidation" icon="shield-check">
    * **Proves it first** — every candidate node is simulated before anything is touched. Taints/tolerations, nodeSelector, and CPU/memory/pod-count must fit on surviving nodes, or the node is dropped from the plan.
    * **Drains gently** — at most 2 nodes cordoned at once (current + look-ahead next), never a fleet-wide cordon.
    * **Waits for health** — pods move a few at a time through the PDB-respecting Eviction API (max 10 in-flight), waiting for each owner's replacement to come back Ready.
    * **Self-heals** — a pending-pod safety valve (baseline + 20) aborts and un-cordons at the first sign of trouble; stops within 5 min of the window end.
    * **Bin-packs to fewer, cheaper nodes** as the goal — cost savings, not just a drain.
  </Card>
</CardGroup>

An illustrative consolidation run:

| Metric            | Before | After   |
| ----------------- | ------ | ------- |
| Nodes             | 23     | **14**  |
| Fleet utilization | 58%    | **89%** |

<Info>
  **Nothing is cordoned until feasibility proves every pod has a home** — so consolidation cuts
  cost without ever causing an outage.
</Info>

See [Node Scale-Down Behavior](/operations/node-scale-down) and
[Cluster Rebalancing](/platform/rebalancing) for the mechanics.

***

## Where to go next

<CardGroup cols={2}>
  <Card title="Getting Started" icon="rocket" href="/guides/getting-started">
    Bootstrap a cluster and deploy Autopilot.
  </Card>

  <Card title="The four engines" icon="layers" href="/platform/pod-resizing">
    Deep-dive each optimization engine.
  </Card>
</CardGroup>
