Free preview

Autoscaling a GPU Fleet

In one line: everything that makes autoscaling work for stateless web servers — a good load signal and fast instance start — is absent here, so the design shifts from reacting to provisioning.

Why the usual signals mislead

**CPU utilisation measures the wrong processor. A GPU worker can be saturated while its CPU idles, so CPU-based scaling reacts either never or to something unrelated.

Request rate ignores that requests differ in cost by orders of magnitude. Fifty short completions and one 100K-context summarisation are not comparable load, and a fleet scaled on request count will be wrong in both directions.

GPU utilisation** is closer and still deceptive. During decode a GPU can report high utilisation while being memory-bandwidth-bound with a half-empty batch — busy, and not doing useful work at capacity.

What to scale on

The useful signals are the ones that describe whether requests are being served on time and whether the hardware has room.

SignalTells youGood for
Queue depth and wait timeDemand is exceeding capacity right nowThe primary scale-up trigger
Time to first token, p95The user-visible contract is slippingThe SLO-anchored trigger
Batch occupancyWhether the engine has room in-flightDetecting real headroom
KV cache utilisationThe memory constraint on concurrencyThe binding limit for long-context traffic
Tokens per second in flightActual work rate, cost-weightedCapacity planning and comparison

Queue wait time is the best single trigger, because it is the thing that directly harms users and it rises before anything else visibly breaks. Pairing it with p95 time to first token gives you a demand signal and an SLO signal, which is a reasonable two-metric answer.

The KV cache row matters for the reason the estimation chapter established: with long contexts, memory binds before throughput does. A fleet serving mixed context lengths needs both signals, because which one saturates first depends on the traffic mix that hour.

The scale-up problem

Even with a perfect signal, the reaction is slow.

Detect sustained pressure          30-60 s
Acquire an accelerator             seconds to MINUTES, if available at all
Pull the container image           1-5 min   (image sizes are large)
Load model weights into GPU        1-5 min   (tens to hundreds of GB)
Warm up, health check              30-60 s
                                   ---------
Total                              ~5-15 minutes

A spike lasting five minutes is entirely over before a new worker serves its first token. So autoscaling does not solve spikes here — it solves sustained shifts in demand, like a daily traffic curve.

Which means spikes must be handled by the mechanisms from the queueing lesson: admission control, degradation and shedding. That connection is the point of this lesson, and it is worth stating explicitly rather than leaving implied.

The third branch is the underrated one. Most products have a demand curve that is roughly the same every weekday, and pre-warming on a schedule beats reacting every single time — you already know the peak is coming at 9am.

Provision for headroom, not for the average

Because reaction is slow, the fleet must carry enough spare capacity to absorb a spike while new workers start.

That headroom is a real cost and choosing it is a business decision: too little and every spike degrades users, too much and you pay for idle accelerators. The honest framing is that you are buying insurance and the premium is visible on the invoice.

Two things reduce the premium without reducing the protection:

**Fill the headroom with preemptible work. Batch jobs, re-embedding, evaluation runs — work that can be paused instantly when interactive demand arrives. The capacity is reserved for spikes and busy the rest of the time, which is the same colocation argument as the estimation chapter and it applies here specifically as a headroom strategy.

Keep a burst path to a hosted API.** When your fleet is saturated, overflow to a provider endpoint rather than shedding. You pay per-token rates for the overflow only, and it converts a capacity failure into a cost spike — which is usually the better trade.

Key takeaway

CPU utilisation measures the wrong processor, request rate ignores that requests differ in cost by orders of magnitude, and GPU utilisation reads high on a half-empty batch — scale on queue wait time and p95 time to first token instead, adding KV cache utilisation when contexts are long. But a scale-up takes five to fifteen minutes, so autoscaling handles sustained shifts and never spikes: absorb those with degradation and shedding, and pre-warm on a schedule where the curve is predictable. Carry headroom, fill it with preemptible work, and drain workers properly on the way down.

Next: sharing a fixed fleet between tenants who all think it is theirs.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue