Speculative Decoding & KV-Cache · 5 of 5
System-Level Throughput Wins
Throughput improves fastest when you stop optimizing parts in isolation and start managing the whole path a request takes.
A slow system is rarely slow for one simple reason. It is usually a chain of small waits: a request sits in a queue, a service calls another service too often, a database returns more data than needed, a model endpoint is asked to handle work in the least efficient shape, and every team measures only its own piece. System-level throughput wins come from looking at the entire path, finding where work really piles up, and changing the shape, timing, or placement of that work so more useful outcomes finish per unit of time.
Start with what throughput really means
Throughput is the rate at which a system completes useful work. In a web application, that might be orders processed per minute. In an artificial intelligence application, it might be prompts answered per second, documents summarized per hour, or images classified per batch window.
Throughput is not the same as latency. Latency is how long one unit of work takes from start to finish. Throughput is how many units finish over time. A restaurant can serve one table very quickly and still have poor throughput if the kitchen can handle only a few meals per hour.
The first principle is simple: a system can move work only as fast as its slowest necessary constraint allows. If every request must pass through one overloaded database, one rate-limited application programming interface, or one undersized model endpoint, the rest of the system can be fast and still not matter.
Local speed can make the whole system worse
A common mistake is to improve one component without asking what happens downstream. If an intake service is made twice as fast, but the database behind it is unchanged, the result may be longer queues, more timeouts, and more retries. The component got faster; the system got less stable.
This is why throughput work begins with the whole path. You need to know what every unit of work touches, which steps are required, which steps can be delayed, and which steps are repeated unnecessarily. The map matters before the tuning.
Another trap is averaging. Average latency can look healthy while a small percentage of requests are painfully slow. Those slow requests consume workers, hold connections, and trigger retries. Tail latency, meaning the slow end of the distribution, often controls real throughput under load.
Find the bottleneck, then prove it
A bottleneck is the point that most limits the rate of completed work. It may be a central processing unit, a graphics processing unit, a database lock, a network link, a model rate limit, a thread pool, a human approval step, or an external dependency. The bottleneck is not always the component with the highest bill or the most visible dashboard.
You identify a bottleneck by watching what builds up. If requests wait before entering a service, the service may be constrained. If workers are idle while waiting for storage, storage may be constrained. If database utilization is low but lock wait time is high, the shape of access may be the issue rather than raw capacity.
A practical test is to change one thing and look for movement in completed work, not only resource usage. If you add workers and throughput does not rise, workers were not the bottleneck. If you reduce payload size and throughput rises, data movement was part of the bottleneck.
Change the shape of work
The biggest throughput gains often come from changing how work is packaged. Batching combines many small units into a larger unit so fixed overhead is paid once. This is why sending 100 records in one call is often cheaper and faster than sending 100 separate calls.
Concurrency lets multiple units of work make progress at the same time. It helps when work spends time waiting, such as waiting for a network response. It does not automatically help when all work competes for the same saturated resource. In that case, more concurrency can simply create more contention.
Caching avoids repeated work by reusing a result that is still valid. It is powerful when many requests ask the same question, read the same reference data, or use the same computed context. The discipline is to cache the right thing for the right time, with clear rules for when it expires.
In generative artificial intelligence systems, the shape of work includes prompt size, retrieved context, response length, and model choice. A smaller prompt that contains the right evidence can improve both latency and throughput. A larger model may be needed for hard reasoning, but simpler requests may complete faster and cheaper on a smaller model.
- Batch small, similar operations when users do not need each result immediately.
- Use concurrency for waiting work, not as a cure for every capacity problem.
- Cache stable reference data, repeated retrieval results, and expensive computations with clear expiration rules.
- Reduce unnecessary payload, prompt, and response size before buying more capacity.
Use queues to absorb bursts without lying to users
Real systems receive uneven demand. A quiet hour can be followed by a sudden spike caused by a campaign, a deadline, a partner feed, or a breaking event. If every request must be processed immediately, the system must be sized for the worst moment or it will fail under bursts.
A queue separates acceptance of work from completion of work. The front door can accept a request, place it in a durable queue, and let workers process items at a controlled rate. This protects fragile downstream systems and makes bursts survivable.
Queues do not create capacity. They create time. If work arrives faster than it can be completed for long enough, the queue will grow without bound. That is why queues need backpressure, which is a way to slow or reject new work before the system collapses. Good backpressure is honest: it tells callers to wait, retry later, choose a lower-cost option, or accept delayed completion.
Measure completed outcomes, not just busy machines
Utilization measures how busy a resource is. It is useful, but it is not the same as throughput. A system can be 100 percent busy doing retries, rework, logging too much data, or waiting on locks. Busy does not always mean productive.
The most useful throughput dashboard starts with completed outcomes per time window, then shows the queues, waits, errors, retries, and saturation points that explain changes. This keeps attention on user and business value rather than on isolated machine behavior.
For applications built with services such as Microsoft Foundry, the same principle applies. Track useful completions, model call rates, token volume, retrieval time, error rates, and downstream waits together. A model endpoint may look like the obvious constraint, but the real limit may be excessive context retrieval, oversized prompts, or repeated calls caused by poor orchestration.
- Completed work per minute or per hour
- End-to-end latency and tail latency
- Queue depth and age of oldest item
- Error and retry rates
- Resource saturation and wait time
- Cost per completed outcome
Make throughput a design decision, not a late-stage rescue
Leaders and practitioners face trade-offs that cannot be solved by tuning alone. Should the system answer immediately or promise completion later? Should premium users receive reserved capacity? Should a simpler model handle routine work while a stronger model handles exceptions? Should the team spend on larger infrastructure or remove unnecessary work from the path?
These are product, architecture, and operating decisions at the same time. A leader needs service goals that name the expected rate, acceptable delay, burst behavior, and failure mode. An engineer needs permission to build for those goals: queues where delay is acceptable, limits where overload is dangerous, caching where reuse is safe, and observability where facts are needed.
The healthiest throughput programs are iterative. Map the path, measure the constraint, change one design lever, and measure again. When the bottleneck moves, that is progress. The goal is not to make every part fast. The goal is to make the whole system complete more valuable work, predictably and safely.
Key takeaways
- Throughput is the rate of completed useful work; latency is the time one unit of work takes.
- The slowest required constraint sets the practical limit for the whole system.
- Local optimizations can hurt total throughput if they overload a downstream bottleneck.
- Batching, concurrency, caching, and smaller payloads improve throughput by changing the shape of work.
- Queues smooth bursts, but sustained overload still needs backpressure, more capacity, or less work.
- Measure completed outcomes, queue behavior, waits, retries, and cost together.
Glossary
- Throughput
- Throughput is the rate at which a system completes useful work over time.
- Latency
- Latency is the time one unit of work takes from start to finish.
- Bottleneck
- A bottleneck is the part of a system that most limits the rate of completed work.
- Batching
- Batching is combining multiple small units of work so shared overhead is paid once.
- Concurrency
- Concurrency is allowing multiple units of work to make progress during the same period.
- Caching
- Caching is storing a result so it can be reused instead of recomputed or refetched.
- Queue
- A queue is a holding place where work waits until a worker can process it.
- Backpressure
- Backpressure is a control that slows, delays, or rejects new work when the system is near overload.
- Utilization
- Utilization is a measure of how busy a resource is during a period of time.