The serving layer
Where most of the recoverable money sits, and the last place anyone looks. Every serving framework ships defaults tuned for a benchmark, and almost nobody revisits them against the traffic they actually get.
The question to ask yourselfWhat is your GPU utilization during an ordinary business hour, not at peak?
Batching sized for the install, not the traffic
What it looks likeRequests queue while the card sits half idle
Concurrency and batch limits get set once and never tuned against real arrival patterns. This is routinely the largest single recoverable number in the stack, and it costs nothing but configuration.
Prefill blocking decode
What it looks likeTail latency spikes whenever a long prompt lands
One long prompt stalls every decode in flight behind it. Chunked prefill and a scheduler that keeps the two phases apart fix it without buying hardware.
No prefix caching on a shared preamble
What it looks likeIdentical leading tokens recomputed on every request
A long system prompt or a RAG preamble means you are paying to compute the same tokens on every call. The fix is a configuration flag and a cache budget.
Speculative decoding left on the table
What it looks likeDecode-bound workload with compute to spare
Memory-bound decode has idle FLOPs. Whether a draft model pays for itself depends on the acceptance rate for your traffic, which is a day of measurement rather than a matter of opinion.