Tailspin Lab

A deterministic queue bench. Bursty requests arrive, a fixed pool of workers serves them, service times vary. Change one thing, then compare the run against a pinned baseline and scrub through ten minutes to see when the queue spins up — and why the average never warned you.

Fictional sample: “Pebblecast”, an invented thumbnail-resizing service. Its baseline sees a steady 3.2 requests/s; the experiment receives the same average traffic, but in bursts. Same mean, same workers, same handlers — very different tail.

Experiment controls

Average requests per second over the 10-minute window.

How much traffic crowds into short bursts. The average stays the same.

Requests served at once. Everyone else waits in one FIFO queue.

Average time a worker spends on one request. Individual jobs vary a lot.

Results

Pending queue over time

0:00

Completion latency (rolling 30 s)

Where the latency actually lands

What this run is telling you

p50, p95 and the mean

p50 (median): half of requests finished faster than this. It describes the typical request.

p95: 1 request in 20 took longer than this. If a page makes 20 such calls, most page loads hit at least one of them.

Mean: total time ÷ requests. A few very slow requests drag it up a little, but it blends the quiet minutes with the jammed ones — so it looks tame while the tail is on fire.

Why bursts hurt: during a burst, arrivals exceed what the workers can finish, and the backlog grows every second the burst lasts. The quiet stretch afterwards has to drain it. Latency depends on when you arrive, which no single average can show.

A two-minute tour

  1. Scrub into a shaded burst window. Watch the amber queue climb while the dashed baseline barely moves.
  2. Tap Add a worker. Utilization only drops from 80% to 64%, yet the peak queue and the p95 fall far more than that — headroom is what absorbs bursts.
  3. Drag burstiness to 0, then to 100. Arrival rate never changes — only its shape.
  4. Tap Over the edge: above 100% average utilization, backlog grows over a long run, even if a quiet interval briefly drains this finite sample.
  5. Find a setup you like, Pin as baseline, and try to beat it.
Model assumptions (open the hood)
  • Deterministic: a fixed seed drives everything, so the same settings always produce the same run. Baseline and experiment share the same random draws (common random numbers), so differences come from your settings, not luck.
  • Arrivals: a Poisson process whose rate switches between calm and burst. Each 30 s block contains one 6 s burst window (20% of time) at a fixed seeded offset. Burst rate = mean × (1 + 4 × burstiness); calm rate is lowered so the 10-minute average equals the arrival-rate setting exactly. At 100% burstiness, all traffic lands inside bursts.
  • Service times: lognormal with the chosen mean and coefficient of variation 1.0 (some jobs are quick, a few take 3–5× the mean).
  • Queue: one shared first-in-first-out queue, no timeouts, retries, drops or autoscaling. Workers never idle while someone waits.
  • Pending queue = arrived but not yet started. Completion latency = finish − arrival (waiting + service).
  • Window: requests arrive during 10 minutes. Headline stats include every one of them, even ones that finish after the window ends. The latency chart plots p50/p95 of requests that completed in the previous 30 s.
  • Utilization ρ = arrival rate × mean service ÷ workers — the “average math” shown in the controls panel.
  • Everything runs locally in this page. No network, storage, or tracking.