skip to content

Explain Little's law and how you would use it, together with observed utilization and queue depth, both to choose the number of workers for a queue-driven service and to explain why response time degrades sharply as the pool approaches saturation.

level: seniorimportance: should knowfreq 42%

answer

  1. L = lambda x W, distribution-free, needs stability
  2. busy workers = arrival rate x service time
  3. R = S/(1-rho); 90% -> 10x, 99% -> 100x
  4. queue wait = depth / throughput
  5. variability (Kingman) inflates delay at the same utilization

basics

~20 s

Little's law: in a stable system the average number of items present equals arrival rate times average time in the system, L = lambda x W. Busy workers needed is arrival rate times service time. Response time grows like 1/(1 - utilization), so the last few percent cost enormous latency.

solid answer

~60 s

Little's law states that for any stable system L = lambda x W: average items resident equals arrival rate times average residence time. It is distribution-free - no assumption about arrival or service patterns - which makes it a valid sanity check anywhere. Applied to the workers, the number that must be busy is lambda x S: 500 requests per second at 40 ms of occupancy needs 20 busy workers, so a 20-worker pool is exactly 100% utilized and any variance produces an unbounded queue. That is where queueing theory takes over: for a single server, residence time is S/(1 - rho) with rho the utilization, and Kingman's approximation scales queueing delay by (rho/(1-rho)) times a variability factor. At 50% utilization you wait about as long as you are served; at 90%, nine times as long; at 99%, ninety-nine. So size for a target utilization near 0.6-0.75, and monitor queue depth and queue wait rather than utilization alone - depth turns up first and, by Little's law, predicts the added latency directly: wait equals depth divided by throughput.

code

text · 6 lines
text
measured: lambda = 500 req/s, S = 40 ms occupancy
busy workers needed  L = 500 x 0.040 = 20
at target utilization U = 0.7  ->  N = 20 / 0.7 = 29 workers

later, observed: queue depth 60, throughput 500/s
queue wait = 60 / 500 = 120 ms added to every request

go deeper

for a junior

State L = lambda x W and compute busy workers as arrival rate times service time for a simple example.

for a middle

Add the need for headroom and show that queue wait equals queue depth divided by throughput.

for a senior

Explain the 1/(1-rho) response curve, the variability term, and which metrics to watch and in what order when diagnosing a saturated pool.

for a principal

Set utilization targets per workload class from the metric each is graded on, and use the identity as a cross-check on capacity models and on the correctness of monitoring.

## Little's law For any system in steady state, over a long enough window, ``` L = lambda x W ``` where L is the average number of items in the system, lambda the average arrival rate (equal to the completion rate in steady state), and W the average time an item spends in the system. It requires only stability - nothing about the distribution of arrivals or service times, nothing about scheduling order. That generality is why it holds simultaneously at several boundaries of the same system. Draw the boundary around the **service** (workers only) and it reads L_busy = lambda x S: the average number of busy workers equals arrival rate times service time. Draw it around the **queue** and it reads L_queue = lambda x W_queue. Draw it around **queue plus service** and you get end-to-end latency and total items in flight. ## Sizing with it Suppose measured demand is 500 requests per second and the average task occupies a worker for 40 ms (compute plus any blocking): L_busy = 500 x 0.04 = 20. Twenty workers is the absolute floor - a pool of exactly 20 runs at 100% utilization, which is not a viable operating point. Choosing a target utilization of 0.7 gives about 29 workers. Sizing therefore has two inputs: the demand product lambda x S, and the headroom factor 1/U. ## Why the last few percent are ruinous Utilization rho is the fraction of capacity consumed. For an idealized single server with random arrivals, residence time is ``` R = S / (1 - rho) ``` so the queueing component is S x rho/(1-rho). The consequences: ``` rho 0.50 0.70 0.80 0.90 0.95 0.99 R/S 2.0 3.3 5.0 10.0 20.0 100.0 ``` Utilization is a poor control variable exactly where it matters most: moving from 90% to 95% looks like a five-point change and doubles latency. Kingman's approximation extends this to general arrivals - queueing delay scales as (rho/(1-rho)) x ((Ca^2 + Cs^2)/2) x S, where the C terms are the coefficients of variation of interarrival and service times. Two systems at identical utilization can therefore have wildly different latency: variable service times (a slow 1% of requests) or bursty arrivals inflate the second factor. Adding servers helps twice - it lowers rho, and pooling many servers behind one queue reduces the variability each sees. ## What to measure - **Queue depth** and, better, **queue wait time**. By Little's law average queue wait = depth / throughput, so a depth of 60 at 500 rps means 120 ms of pure waiting added to every request. Depth rises before utilization pins, which makes it the earlier signal. - **Utilization per pool** (fraction of workers busy, and CPU utilization separately). A pool 100% busy while the CPU is idle means the workers are blocked on something else - the pool is not the bottleneck, the dependency is. - **Service time distribution**, not just the mean. The variability term is often the real cause of a bad tail. - **Arrival rate and burst shape.** A mean of 500 rps arriving in 50 ms bursts behaves like a much higher rate. ## Using the law as a cross-check Because the identity must hold, it exposes bad measurements. If throughput is 500 rps, average latency is 200 ms, and the pool has 12 workers with an empty queue, the numbers are impossible: L = 100 items in flight cannot fit in 12 workers, so either latency includes time spent outside the pool, or the queue is not being measured, or the throughput figure is wrong. Interviewers like this use because it separates people who memorized L = lambda x W from those who apply it. ## Limits Steady state is required: during a burst or an outage the law says nothing about the transient. It gives averages only, never percentiles - a tail problem needs the distribution. And it is an identity, not a causal model: it tells you the relationship the three quantities must satisfy, not which one you can change.

  • Your pool reports 100% of workers busy but host CPU sits at 15%. What does that tell you?
    That the workers are blocked, not computing, so the pool is not CPU-limited - it is limited by whatever they are waiting on, or simply undersized for its blocking ratio. Either raise the worker count according to the wait/service ratio, or, if the dependency is itself saturating, recognize that adding workers will only queue on the far side and the real fix is downstream capacity, batching, caching, or load shedding.
  • Why is a target utilization of 95% reasonable for a batch pipeline but not for an interactive service?
    Because the penalty of high utilization is queueing delay, and a batch pipeline is graded on throughput and total completion time, not per-item latency; running it near saturation maximizes work per machine. An interactive service is graded on the latency tail, and at 95% utilization residence time is roughly twenty times service time with any burst pushing it far higher. The right target follows from the metric the workload is judged on.

saying these in an interview costs you the question

  • Treating Little's law as requiring Poisson or exponential arrivals
  • Sizing the pool at exactly arrival rate times service time with no headroom
  • Watching only average utilization and missing a growing queue
  • Assuming latency scales linearly with utilization
  • Ignoring service-time variability, then being surprised the tail is bad at moderate utilization

context