#The SOC as an M/M/c queue
Model alerts arriving as a Poisson process with rate per hour, analysts on shift, and each investigation taking an exponential time with mean . The offered load is Erlangs and utilization is . The probability an alert has to wait at all is Erlang's C formula [1]:
the mean wait in queue is
and the wait-time tail is exponential: .
Our scenario: 1,200 alerts per day (/hour), 12 minutes per manual investigation (/hour per analyst). Offered load is 10 Erlangs, so you need more than 10 analysts on shift simply for the queue to be finite.
#The utilization cliff
| Analysts on shift | Utilization | P(wait) | Mean wait (Erlang C) | Mean wait (sim, exp.) |
|---|---|---|---|---|
| 11 | 91% | 68% | 8.2 min | 7.9 min |
| 12 | 83% | 45% | 2.7 min | 2.8 min |
| 13 | 77% | 29% | 1.1 min | 1.2 min |
| 14 | 71% | 17% | 0.5 min | 0.6 min |
| 16 | 63% | 6% | 0.1 min | 0.1 min |
Going from 11 to 12 analysts — one more person on a shift of eleven — cuts mean wait from 8.2 to 2.7 minutes. Removing one from eleven makes the queue infinite. This non-linearity is the most important fact about SOC staffing: at high utilization, small changes in volume or headcount produce huge changes in response time, and alert volume is never constant.
The simulation column comes from a discrete-event simulation of 60 days of alerts with exponential handling times. It agrees with Erlang C to within simulation noise, which validates the simulator for the next step.
#Variance doubles the wait
Real investigations are not exponential. Most alerts take a couple of minutes; a few take hours. We re-ran the simulation with lognormal handling times of the same 12-minute mean and a coefficient of variation . The Allen–Cunneen approximation predicts the M/G/c wait from the M/M/c one:
| Analysts | Erlang C | Allen–Cunneen | Simulated (lognormal) | Sim. 95th percentile | Sim. share waiting > 30 min |
|---|---|---|---|---|---|
| 11 | 8.2 min | 13.3 min | 12.5 min | 58 min | 14.3% |
| 12 | 2.7 min | 4.4 min | 4.0 min | 20 min | 1.9% |
| 13 | 1.1 min | 1.9 min | 1.7 min | 10 min | 0.4% |
| 14 | 0.5 min | 0.8 min | 0.7 min | 5 min | 0.0% |
With 11 analysts, 14% of alerts wait more than 30 minutes before anyone opens them — longer than the 48-minute average eCrime breakout time CrowdStrike reported for 2024 [2], once you add the investigation itself. The practical lesson: a handful of long investigations can starve the whole queue. Splitting work by expected duration (fast lane for quick closes, a separate lane for deep investigations) reduces waits more than adding a generalist.
#What AI pre-triage changes
Model an AI triage layer that closes a fraction of alerts with evidence before a human sees them, and attaches an investigation summary to the rest that shortens human handling time by a factor . The human queue then sees arrivals with service rate . We computed the minimum analysts on shift that keep mean wait at or under 5 minutes:
| Alerts closed by AI (f) | Human handling time factor g | Alerts reaching humans per day | Analysts on shift for ≤ 5 min wait |
|---|---|---|---|
| 0% | 1.0 (no summary) | 1,200 | 12 |
| 0% | 0.6 (summary attached) | 1,200 | 7 |
| 50% | 1.0 (no summary) | 600 | 7 |
| 80% | 1.0 (no summary) | 240 | 4 |
| 80% | 0.6 (summary attached) | 240 | 2 |
| 90% | 1.0 (no summary) | 120 | 2 |
| 95% | 1.0 (no summary) | 60 | 2 |
Two findings are worth stating precisely:
- Summaries matter almost as much as closures at low f. With no autonomous closures, cutting human handling time by 40% reduces required analysts from 12 to 7.
- Returns flatten above 90%. From to the requirement stays at two analysts per shift for a 5-minute wait. Past that point, staffing is set by coverage and resilience (someone must be able to respond while someone else is on a call), not throughput. Spend the remaining effort on the accuracy of what is closed — see our base-rate analysis.
#Turning this into a staffing plan
- Measure hourly alert arrival rates for a month; plan for the 90th-percentile hour, not the daily average.
- Measure handling-time distribution (mean and spread). Your is probably above 1.
- Pick a wait target tied to threat speed — e.g. 95% of alerts opened within 10 minutes.
- Solve for per shift with Erlang C, then multiply by the Allen–Cunneen factor or simulate.
- Remember that one 24/7 seat needs roughly five full-time people once you account for shifts, leave and training.
#From seats to headcount
Queueing results are in analysts on shift. A 24/7 seat is 168 hours a week; a full-time analyst delivers roughly 35 productive hours a week after leave, training and meetings. That makes each 24/7 seat about FTE.
| Scenario | Analysts on shift | Approx. FTE for 24/7 |
|---|---|---|
| No AI, 5-minute mean wait | 12 | 58 |
| No AI, investigation summaries only (g = 0.6) | 7 | 34 |
| AI closes 80%, summaries on the rest | 2 | 10 |
The first row is why most mid-size organizations don't run a 24/7 internal SOC and why MDR exists. The third row is a staffing level a mid-size company can actually hire — but notice it is set by the 5-minute wait target and by having two people per shift, not by alert volume. Nobody should be the only person on shift during an incident.
Computing Erlang C yourself
from math import factorial
def erlang_c(lam, mu, c):
a = lam / mu
top = a**c / factorial(c) * c / (c - a)
p_wait = top / (sum(a**k / factorial(k) for k in range(c)) + top)
return p_wait, p_wait / (c * mu - lam) # P(wait), mean wait in hours
print(erlang_c(50, 5, 12)) # (0.449, 0.045) -> 2.7 minutes
#Staff for the peak hour, not the day
Alert volume is not flat. If the busiest hour carries twice the average rate, the same Erlang C calculation gives very different answers:
| Arrival rate | Offered load | Analysts for ≤ 5 min mean wait | Wait with 12 analysts |
|---|---|---|---|
| 25 / hour (quiet hour) | 5 Erlangs | 7 | under 0.1 min |
| 50 / hour (average) | 10 Erlangs | 12 | 2.7 min |
| 100 / hour (peak hour) | 20 Erlangs | 22 | unbounded — queue grows all hour |
A team sized for the daily average is overloaded every peak hour, and a queue that grows for an hour takes hours more to drain. This is where an automated first pass earns its keep: it absorbs peaks without a staffing plan, because its capacity scales with compute rather than shifts.
#Limitations
Alert arrivals are bursty and correlated (one incident triggers many alerts), which Poisson arrivals understate; burstiness makes waits worse. Analysts are not interchangeable servers, and they don't work alerts strictly first-in-first-out. The AI layer is modeled as perfectly accurate on what it closes, which it is not; the base-rate post quantifies that trade-off. All scenario parameters are illustrative.
#Frequently asked questions
How many SOC analysts do I need?
Divide alert volume per hour by investigations per analyst per hour to get the offered load in Erlangs; you need more analysts on shift than that number just to keep the queue finite, and typically 15–25% more to keep waits short. Then account for roughly five full-time staff per 24/7 seat.
Does AI triage reduce SOC headcount?
In our model, an AI layer that closes 80% of alerts and attaches summaries to the rest cut the analysts needed per shift from 12 to 2 for a 5-minute mean wait. Above about 90% closure, staffing is driven by coverage and resilience rather than throughput.
#Sources
- [1] L. Kleinrock, Queueing Systems, Volume 1: Theory. Wiley, 1975
- [2] CrowdStrike, 2025 Global Threat Report (average eCrime breakout time 48 minutes in 2024; fastest 51 seconds)
Put your queue on a diet.
Nightwatch investigates every alert in about a minute and hands humans a short, evidenced queue. Run a two-week shadow trial and measure your own f and g.
Book a briefing