Learn
Lesson · Markov Chains, Decisions and Queues · The named queues

More Servers, and Erlang C Read Off π

One line changes. Below s customers an arrival finds a free server, so adding a customer adds a busy server and the service rate rises with n; at and above s every server is busy and the rate stops rising. That is μₙ = min(n, s)μ, and the cut equations do not notice, because they were never told the rates were constant. Erlang C is not a second formula on this page: the probability an arrival has to wait is the probability the system is already at s or above, which is πₛ + πₛ₊₁ + ⋯, added up from the distribution the cuts produced. The closed form from the System Design core sits beside it.

μₙ = min(n, s)μ one change to one list, and that is all of M/M/s offered load a = λ/μ, utilisation ρ = a/s; a does not change when s does P(an arrival waits) = P(N ≥ s) = πₛ + πₛ₊₁ + ⋯ a reading, not a formula a = 2: one server 100%, two 96.296%, three 44.444%, four 17.391%, five 5.970% at s = 3 the closed form erlangC gives 4/9 = 44.444%, and the two agree busy servers = a only when the queue settles: at a = 2, s = 1 it is 1, not 2
One line changed, and the waiting probability collapsing at fixed load

Core ideas

What this lesson establishes

Three ideas. The first is the model, the second is what Erlang C actually is, and the third is a sentence that is true only under a condition and used to be printed without it.

1

Several servers is one change to the service-rate list

With n customers and s servers, min(n, s) of them are busy, so the completion rate out of state n is min(n, s)μ. Below s the chain speeds up as it fills; at and above s it cannot speed up any further. Nothing else about the model changes, and the cut equations apply unaltered because they never assumed a constant rate.

2

Erlang C is a reading of π, not a second derivation

An arriving customer waits exactly when every server is already busy, that is when the system is at state s or above. So the waiting probability is Σ_{n ≥ s} πₙ, summed from the distribution the cuts produced. The closed form erlangC from sysdesign_core is printed beside it as a check on the truncated chain, and at three servers on the worked load both give 44.444%.

3

Adding a server does not reduce the work, only the waiting

The offered load a = λ/μ is a property of the arrivals and the service, and neither moves when a server is added: the same work arrives and, while the queue settles, the same work is done. What collapses is the probability of waiting — from 96.296% at two servers to 44.444% at three to 17.391% at four, at a fixed load of 2. That is the argument for pooling as a number.

The material

s servers, the same work, far less waiting

The rate list, the waiting probability read off π, the pooling table, and the one sentence that needed a condition attached to it.

Definition · The M/M/s chain

A birth-death chain with λₙ = λ for every n and μₙ = min(n, s)·μ, where μ is the rate of ONE server. Write a = λ/μ for the offered load and ρ = a/s for the utilisation per server.

An arriving customer waits when all s servers are busy, which is exactly when the system is in state s or above. That probability is Erlang C.

Two ratios and it is easy to use the wrong one. a = λ/μ is how much work arrives per unit time, measured in server-loads; it is 2 on the worked example whether there are two servers or five. ρ = a/s is the fraction of each server's time that work would occupy, and it is the one that has to be below 1 for an unbounded queue to settle.

λ = 2, μ = 1 (per server), s = 3 a = 2, ρ = a/s = 2/3 service rate out of state n: n = 1 → 1 n = 2 → 2 n = 3 → 3 n = 4 → 3 and 3 thereafter cut ratios: 2/1, 2/2, 2/3, 2/3, 2/3, … weights: 1, 2, 2, 4/3, 8/9, 16/27, … π₀ = 0.111111 π₁ = 0.222222 π₂ = 0.222222 π₃ = 0.148148 π₄ = 0.098765 π₅ = 0.065844 P(wait) = π₃ + π₄ + π₅ + ⋯ = 44.444% sysdesign_core.erlangC(2, 1, 3) = 4/9 = 44.444%

The two figures are computed from different things. The left one is a sum of entries of the truncated chain's π; the right one is the closed form for an unbounded M/M/s, 4/9 exactly. They agree to well under a millionth here, and the page prints a green tick when they do. On a chain kept too short for its load they will not, and the page will say so — which is the correct behaviour, because the disagreement is real and belongs to the truncation.

Pooling, at a fixed load

the same offered load a = 2, spread over more servers servers ρ = a/s P(wait) Lq Wq each server busy 1 2 100.000% 38.00000 38.00000 100.00% 2 1 96.296% 18.29630 9.37975 97.53% 3 2/3 44.444% 0.88889 0.44444 66.67% 4 1/2 17.391% 0.17391 0.08696 50.00% 5 2/5 5.970% 0.03980 0.01990 40.00% the offered load is 2 in every row, and the waiting collapses anyway

The third row is where the system becomes usable and the second is where it is not. At two servers ρ = 1 exactly: the work arriving equals the work the servers can do, the unbounded queue does not settle, and the only reason a finite Lq appears at all is the truncation at forty states. At three the utilisation is two thirds and the waiting probability has fallen by more than half. Nothing about the arrivals or the service changed between those rows.

Notice also the last column. Each server is busy 66.67% of the time at three servers and 40% at five, so the per-server utilisation falls as the waiting falls — which is the price of pooling and the reason it is a trade rather than a free lunch. “Many Servers: Pooling, and Erlang C” makes the same comparison from the closed forms; this page makes it from a distribution you can see.

The sentence that needed a condition

The expected number of busy servers is Σ min(n, s)πₙ, and on a queue that settles it equals the offered load a: every arriving customer is eventually served, so the work completed per unit time equals the work arriving, and adding a server does not change either. At a = 2 the busy count is 2.0000 at three servers, at four and at five.

Example · Where busy servers equals offered load stops being true

Set λ = 2, μ = 1 and one server. The offered load is still 2. The expected number of busy servers is 1.0 — it cannot exceed s = 1 — and the work the server finishes is 1 per unit time against the 2 arriving.

So “on average a's worth of work is being done, whatever s is” is false here, and this page used to print it without a condition. The banner now branches on ρ: below 1 it states the identity, and at ρ ≥ 1 it says instead that the servers cannot keep up, prints what they do finish, and notes that only the truncation stops the difference piling up without bound.

That correction is worth dwelling on, because the false version is more memorable than the true one and survives being half-remembered. The identity “throughput equals offered load” is a conservation statement about a system in equilibrium, and a system at ρ ≥ 1 has none; what it has is a backlog growing at λ − sμ per unit time, which “Transient Overload and Draining the Backlog” is about.

Example · Two servers at three quarters loaded

With λ = 3, μ = 2 and two servers the offered load is 3/2 and ρ = 3/4. The chain gives P(wait) = 64.285% and Lq = 1.928, and the closed form gives 64.286%.

The two differ by about three parts in a million, which is larger than the page's own agreement threshold, so it prints a disagreement here even though nothing is wrong: the chain is kept to forty states at a load whose tail decays like (3/4)ⁿ. The lesson is the one the preceding material made — a truncated chain is a different model — and the threshold is a property of this page rather than of the mathematics.

Interactive

More servers, the same work, far less waiting

one change to the rate list, and Erlang C read off the distribution it produces

The service rate rises until every server is busy, then stopsμₙ = min(n, s)μ — one change to one list, and Erlang C falls out
states with an idle serverstates where an arrival has to waitErlang C, from the System Design coreservice rate per state

Method

Sizing a bank of servers

Four steps. The first two are about which ratio you are holding, and the fourth is the one that turns a table into a decision.

1

Compute the offered load first, and keep it separate from the utilisation

a = λ/μ in server-loads, ρ = a/s per server. a is a property of the demand and the service; ρ is what you change by adding capacity. Writing both down stops the standard slip of comparing a load of 2 against a utilisation of 2.

2

Build the rate list with min(n, s)μ and hand it to the same machinery

No new model and no new formula. The cut equations give the ratios, the product gives the weights, normalising gives π, exactly as on a single server.

3

Read the waiting probability off π rather than computing it

P(wait) = Σ_{n ≥ s} πₙ. This is what Erlang C is. Having it as a sum rather than as a formula is what lets you answer a variant — a finite waiting room, a customer who balks — where the formula does not apply.

4

Compare across s at fixed a, and price the idle capacity

Hold the load and vary the servers: the waiting probability falls sharply and the per-server utilisation falls with it. Both columns are the decision. A table that shows only the waiting makes pooling look free.

Servers, load and waiting

Score 0 / 0

A three-server desk at an offered load of two, and the same load on one to five servers

Arrivals at 2 per unit time, each server completing 1 per unit time. The offered load is 2 in every row below; only the number of servers changes.

λ = 2, μ = 1 per server, s = 3 a = 2, ρ = 2/3 service rates out of states 1, 2, 3, 4, …: 1, 2, 3, 3, … cut ratios 2, 1, 2/3, 2/3, … weights from π₀ = 1 1, 2, 2, 4/3, 8/9, 16/27, … π 0.111111 0.222222 0.222222 0.148148 0.098765 0.065844 n = 0 n = 1 n = 2 n = 3 n = 4 n = 5 an arrival waits when n ≥ 3: P(wait) = π₃ + π₄ + π₅ + ⋯ = 44.444% erlangC(2, 1, 3) = 4/9 = 44.444% the two differ by 5.0e-8, which is the truncation at 40 states Lq from the chain 0.88889 closed form 8/9 Wq 0.44444 busy servers 2.0000 of 3 the same load on one to five servers s ρ P(wait) Lq each server busy 1 2 100.000% 38.00000 100.00% 2 1 96.296% 18.29630 97.53% 3 2/3 44.444% 0.88889 66.67% 4 1/2 17.391% 0.17391 50.00% 5 2/5 5.970% 0.03980 40.00% and the case the banner had to be fixed for: λ = 2, μ = 1, s = 1: a = 2, busy servers = 1.0, not 2

The Lq column is the one that makes the case. Going from two servers to three takes the expected queue from about eighteen to under one — a factor of twenty for one more server, at a load that did not change. That is not a smooth trade-off; it is the collapse that happens as ρ comes away from 1, and “The Knee: Response Time vs Utilisation” is the same phenomenon seen from the other side.

The two-server row deserves suspicion rather than admiration. ρ = 1 exactly, so the unbounded queue does not settle at all and Lq = 18.3 is a fact about keeping forty states. Drag the state count up and it grows; the closed form refuses the row entirely. A finite number appearing where none should is exactly the failure mode the preceding material warned about.

The last line is the honesty fix. At one server the offered load is 2 and the busy count is 1, so the tidy sentence “busy servers equals the offered load whatever s is” is false. It is true while the queue settles, and the page now branches on ρ and says the other thing when it does not.

For a rehearsal, keep three servers and raise λ from 2 to 3. The supplied first move is that a becomes 3 and ρ becomes 1. Predict what happens to P(wait) and to the agreement with the closed form, then check: one of the two columns stops existing, and the other keeps printing a number.

Common mistakes

1
Comparing the offered load against 1 instead of the utilisationa = λ/μ can be 4 on a perfectly comfortable five-server system. The condition for an unbounded queue to settle is ρ = a/s < 1. Writing both down and labelling them removes the whole class of error, and the lab prints them as two separate figures for that reason.
2
Quoting a finite queue length at ρ = 1The unbounded queue has no stationary distribution at ρ = 1, so any Lq you see is a property of the state count. It grows as you keep more states. The closed form refuses the case; a truncated chain will happily print 18.29630 and look like an answer.
3
Saying that the servers do a's worth of work whatever s isTrue while the queue settles and false otherwise. At a = 2 with one server the busy count is 1, not 2, and the missing work is piling up. The sentence needs ρ < 1 attached to it every time, which is why the page branches rather than printing one version.

Check your understanding

✓
Finish when adding a server is a change you can make to one list, and Erlang C is a sum you can point at in a distribution.

You should be able to write μₙ = min(n, s)μ, keep the offered load and the utilisation apart, read the waiting probability off π as P(N ≥ s), produce the pooling table at a fixed load and read both of its consequences, and state the condition under which busy servers equals offered load together with a case where it fails.

Note: Every chain so far has been truncated as an approximation and apologised for it. The next one is truncated on purpose: a system with a waiting room of size K loses the arrivals that find it full, so the wall is the model rather than a compromise. ρ ≥ 1 stops mattering entirely, and one division becomes two. “Finite Buffers, Blocking and the Admitted Rate” prints both of them side by side.

Kept in this browser only, for you. Nothing is sent anywhere and nothing checks it. Carry it to another device.

Feedback and recommendations

Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.

No recommendations yet for this lesson.