Guide

A chat endpoint that looks healthy at noon can miss its TTFT SLO by 4 pm because three replicas are stuck with full KV caches while CPU and GPU utilization still read "busy but fine." Autoscaling for LLM inference is not web-app autoscaling. The scarce resources are HBM and tokens in flight. Cold starts take minutes. The wrong scale-down kills live streams.

The control loop is the same as any scaler: measure demand, compare it to a target, add or remove capacity. The measurement is what changes. Pair this with cost per token when you turn capacity into dollars, and with GPU infrastructure when you need the node and driver layer.

Concepts in this section

Read them in order. Each one builds on the one before.

StepConceptWhat it answers
1Scaling signalsWhy do CPU and GPU util lie, and what should you scale on?
2Cold startsHow long until a new replica can serve, and how do you hide that?
3Scale-to-zeroWhen is it safe to let the last replica exit?
4GPU fleet planningReserved vs burst, and which GPU class for which model?
5Replica drainHow do you scale down or lose a GPU without cutting streams?

Why this is a production problem

A replica at the real limit — waiting queue growing, KV at 90%+ — often shows the same GPU util as an underloaded one, because decode is memory-bound. Scaling on that gauge adds replicas too late, or not at all.

Even a correct signal is late if boot takes six minutes. Image pull, ~70 GB of 70B FP8 weights, compile caches and CUDA graphs all sit on the critical path. Startup probes copied from a Node service will kill the pod while it is still loading.

The weekly job looks like this: read concurrency and TTFT against the benchmark envelope; set KEDA thresholds on queue and KV; keep a warm pool sized to cold-start × ramp rate; review reserved vs on-demand mix against last month's GPU bill.

Common mistakes

  • Scaling on GPU util. It does not tell you if the replica can admit more work.
  • Reactive HPA with no warm pool. Traffic ramps in minutes; 70B boots take minutes more.
  • Scale-to-zero on interactive paths. The first request after idle pays the full cold start.
  • SIGTERM while a stream is live. The Deployment looks healthy. The user sees a truncated answer.

Key takeaways

  • Scale on queue depth, KV utilization, in-flight tokens and TTFT, not busy percentage.
  • Cold starts are measured in minutes. Size warm pools to that horizon.
  • Interactive paths keep minReplicas or a shared multi-LoRA host. Scale-to-zero is for batch and long-tail.
  • Fleet shape is reserved baseline plus burst, with models pinned to the right GPU class.
  • Drain streams on scale-down. Treat GPU failure as a first-class reliability case.

Further learning

KubeCon EU 2025 talk on autoscaling LLM workloads with OpenTelemetry + KEDA on KV-cache and queue metrics:

Optimizing Metrics Collection & Serving When Autoscaling LLM Workloads - Vincent Hou & Jiří KremserCNCF [Cloud Native Computing Foundation]

KEDA maintainers on event-driven scaling beyond CPU HPA:

KEDA: Unlocking Advanced Event-Driven Scaling for Kubernetes - Zbynek Roubalik & Jorge TurradoCNCF [Cloud Native Computing Foundation]
KServe documentationKServe - A Kubernetes-native platform for serving machine learning models with standardized protocols for both predictive and generative AI. Scale to zero, GPU acceleration, and multi-framework support.kserve.github.io KEDAApplication autoscaling made simpleKEDA