Applications of ORGitHub
Lecture 7 · Services & Workforce

Call Centre Staffing

Sizing a call centre with the Erlang C queue, service-level targets, and the square-root staffing rule.

A customer-service centre receives telephone calls at random times. Each call needs an agent for a few minutes; if all agents are busy, the caller waits in a queue, listening to music. Agents are expensive, but so are long waits — customers hang up, complain, or take their business elsewhere. How many agents should be on duty in each half-hour?

This is the staffing problem for call centres (and, with different vocabulary, for emergency dispatch, help desks, hospital admissions and checkout lanes). Its classical answer is a hundred-year-old queueing formula due to A. K. Erlang, a Danish mathematician at the Copenhagen Telephone Company, who developed it to size telephone exchanges. The formula, together with a remarkably accurate rule of thumb derived from it, is still at the heart of every workforce management system sold to contact centres.

The decision

Fix a single planning period — say a half-hour — in which conditions are roughly stable.

  • Calls arrive at an average rate of λ\lambda per unit time.
  • Each call occupies an agent for an average handle time hh (talk time plus after-call work). The service rate per agent is μ=1/h\mu = 1/h.
  • Management sets a service-level target, most commonly of the form "at least 80% of calls answered within 20 seconds", written 80/20.

The decision is the number of agents cc. More agents means shorter waits and a higher wage bill; we want the smallest cc that meets the target. The answer becomes the staffing requirement rtr_t for that period, which feeds the shift scheduling model of the previous lecture.

(Offered load)

The offered load is a=λ/μ=λha = \lambda / \mu = \lambda h, measured in Erlangs. It is the average number of agents that would be busy if every call were answered immediately. With cc agents the utilization (or occupancy) is ρ=a/c\rho = a / c.

A stable queue needs c>ac > a: if agents could, on average, handle no more work than arrives, the queue would grow without bound. So aa is a hard floor on staffing; the question is how much safety staffing c−ac - a to add on top.

Formulation

The standard model is the M/M/c queue: arrivals form a Poisson process with rate λ\lambda (the first M), handle times are independent and exponentially distributed with mean hh (the second M), there are cc identical agents, callers wait in a single first-come first-served queue, and nobody hangs up.

Under these assumptions the long-run behaviour has closed forms. Let WW be the waiting time (before reaching an agent) of an arriving call.

(Erlang C formula)

If a<ca \lt c, the probability that an arriving call has to wait is

C(c,a)=P(W>0)=acc! cc−a∑k=0c−1akk!+acc! cc−a.C(c, a) = P(W > 0) = \frac{\dfrac{a^c}{c!}\,\dfrac{c}{c - a}}{\displaystyle\sum_{k=0}^{c-1} \frac{a^k}{k!} + \frac{a^c}{c!}\,\frac{c}{c - a}} .

Conditional on having to wait, WW is exponentially distributed with rate (c−a)/h(c - a)/h.

The second statement makes the two standard performance measures easy to compute.

  • Average speed of answer (ASA), the mean wait over all calls, including those answered at once:
ASA=E[W]=C(c,a) hc−a.\text{ASA} = \mathbb{E}[W] = C(c, a)\, \frac{h}{c - a} .
  • Service level, the fraction of calls answered within a threshold τ\tau:
SL(τ)=P(W≤τ)=1−C(c,a) e−(c−a)τ/h.\text{SL}(\tau) = P(W \le \tau) = 1 - C(c, a)\, e^{-(c - a)\tau / h} .

The staffing problem is then the one-dimensional integer optimization

c∗=min⁡{c∈Z:c>a,  SL(τ)≥α},c^* = \min \left\{ c \in \mathbb{Z} : c \gt a, \; \text{SL}(\tau) \ge \alpha \right\},

where α\alpha is the target fraction (0.8 for an 80/20 target). Because the service level increases with cc, the answer is found by trying c=⌊a⌋+1,⌊a⌋+2,…c = \lfloor a \rfloor + 1, \lfloor a \rfloor + 2, \dots until the target is met.

Evaluating the formula directly overflows for large cc because of the factorials. A stable route is the Erlang B recursion B0=1B_0 = 1, Bk=aBk−1/(k+aBk−1)B_k = a B_{k-1} / (k + a B_{k-1}), followed by C(c,a)=cBc/(c−a(1−Bc))C(c, a) = c B_c / (c - a(1 - B_c)). Here BcB_c is the blocking probability of a system with cc servers and no waiting room.

Solution methods

For a single period the exact search above takes microseconds, so computation is not the issue. What matters is understanding how the answer scales with the load, and for that the key result is the square-root staffing rule.

Square-root staffing. Write the number of agents as the offered load plus a multiple of its square root:

c=a+βa,c = a + \beta \sqrt{a},

where β>0\beta \gt 0 is a quality-of-service parameter. The intuition is that the number of calls in progress, if every caller were served immediately, is Poisson with mean aa and standard deviation a\sqrt{a}; safety staffing proportional to a\sqrt{a} is safety stock against that variability, exactly as in inventory theory.

(Halfin–Whitt regime)

Let the load a→∞a \to \infty with c=a+βac = a + \beta\sqrt{a} for a fixed β>0\beta \gt 0. Then the probability of waiting converges to a limit strictly between 0 and 1:

P(W>0)  →  [1+β Φ(β)φ(β)]−1,P(W > 0) \;\to\; \left[ 1 + \frac{\beta\, \Phi(\beta)}{\varphi(\beta)} \right]^{-1},

where Φ\Phi and φ\varphi are the standard normal distribution function and density.

This quality-and-efficiency-driven (QED) regime explains the economics of large call centres. Holding β\beta fixed keeps the probability of waiting roughly constant, while utilization a/(a+βa)→1a / (a + \beta\sqrt{a}) \to 1. Large centres can therefore run their agents much harder than small ones at the same service quality: the safety staffing βa\beta\sqrt{a} grows only like the square root of the volume. This is the economies-of-scale argument for pooling small centres into large ones.

The practical recipe is: pick β\beta from the limit formula to hit a target probability of waiting, set c=⌈a+βa⌉c = \lceil a + \beta\sqrt{a} \rceil, and if needed adjust by one using the exact formula.

Worked example

(Sizing one half-hour)

A centre expects 400 calls per hour with an average handle time of 3 minutes, and wants to answer 80% of calls within 20 seconds. The offered load is

a=λh=40060×3=20 Erlangs,a = \lambda h = \frac{400}{60} \times 3 = 20 \text{ Erlangs},

so at least 21 agents are needed for stability. The Erlang C measures for a range of staffing levels are:

Agents ccUtilization ρ\rhoP(W>0)P(W > 0)ASA (s)SL(20 s)\text{SL}(20\,\text{s})
2195.2%0.761136.931.9%
2290.9%0.56851.154.5%
2387.0%0.41624.970.2%
2483.3%0.29813.480.9%
2580.0%0.2097.588.0%
2676.9%0.1434.392.6%
2774.1%0.0962.595.6%
2871.4%0.0631.497.4%

The minimum staffing that meets the 80/20 target is c∗=24c^* = 24 agents: 4 above the load. With 24 agents, about 30% of callers wait at all, the average wait is 13 seconds, and agents are busy 83% of the time.

Two features of the table are worth noticing. First, the marginal value of an agent falls steeply: going from 21 to 22 agents cuts the ASA by nearly 86 seconds, while going from 27 to 28 saves about one second. Second, performance is very sensitive to the load when utilization is high. If call volume turns out 5% above forecast (420 calls per hour, so a=21a = 21), the same 24 agents answer only 69.6% of calls within 20 seconds and the ASA nearly doubles to 25.5 seconds; at 10% above forecast (a=22a = 22) the service level drops to 53.3%.

(Square-root staffing at scale)

Suppose instead the target is "at most 30% of callers wait at all". Solving [1+βΦ(β)/φ(β)]−1=0.3\left[1 + \beta\Phi(\beta)/\varphi(\beta)\right]^{-1} = 0.3 gives β≈0.829\beta \approx 0.829. Applying the rule at three different loads and comparing with the exact Erlang C answer:

Load aaa+βaa + \beta\sqrt{a}Rule (rounded up)Exact minimum ccUtilization at exact cc
2023.71242483.3%
8087.41888890.9%
320334.8333533695.2%

The rule is exact or one agent short — remarkably accurate for a one-line formula. Quadrupling the load from 20 to 80 Erlangs raises the safety staffing only from 4 to 8 agents, and utilization climbs from 83% to 91% with the same chance of waiting.

Limitations and extensions

The M/M/c model is a starting point. Each of its assumptions fails in practice, and the failures have well-developed remedies.

Abandonment. Real callers hang up. In the Erlang A model (M/M/c+M) each waiting caller abandons after an exponentially distributed patience time with mean θ−1\theta^{-1}. Abandonment acts as a safety valve: the queue is stable even when c≤ac \le a, because impatient callers remove themselves. Erlang C, which assumes infinite patience, therefore tends to overstate waits and to recommend more agents than needed when abandonment is significant. The abandonment rate becomes a performance measure in its own right, and service targets are often set on it directly.

Non-exponential handle times. Handle times are typically closer to lognormal than exponential. The Erlang formulas are fairly robust, but for precise work centres use approximations for the M/G/c queue or simulation.

Time-varying arrivals. Call volumes follow strong daily and weekly patterns, so λ\lambda is really λ(t)\lambda(t). The common approach is stationary independent period-by-period (SIPP) staffing: treat each half-hour as a separate stationary M/M/c queue using its own forecast rate, and compute a requirement rtr_t for each period. This works well when periods are long relative to handle times and the rate changes slowly; when the load ramps up sharply, the queue lags behind the arrival rate and SIPP understaffs. Refinements shift the load forward by one handle time, or use the offered load of an infinite-server queue in place of λ(t)h\lambda(t) h.

Forecast uncertainty. The formulas treat λ\lambda as known, but forecasts for a given half-hour are often wrong by 10% or more. Given the sensitivity seen in the worked example, planners add a buffer, or choose staffing to meet the target in expectation over a distribution of possible λ\lambda.

Linking to shift scheduling. The output of this lecture — a requirement rtr_t per half-hour — is precisely the input to the set covering model for shift scheduling. Because shifts are long and requirements vary, the resulting schedule over-covers many periods. Better plans come from integrating the two steps: let the shift model choose staffing levels directly, with a penalty for the service level achieved in each period (a concave, increasing function of agents, which can be approximated piecewise linearly), rather than imposing fixed requirements.

Skills-based routing. Large centres serve several call types (languages, products) with agents who have different skill sets. Deciding who answers which call, and how many agents of each skill combination to hire, leads to queueing networks that are usually tackled with simulation-based optimization.

Further reading: Gans, Koole and Mandelbaum, "Telephone call centres: tutorial, review, and research prospects", Manufacturing & Service Operations Management (2003); Koole, Call Centre Optimization.