# Capacity Curve Analysis – When to Stop Scaling Concurrency

## The Core Question

"Shall we test conc=200?" The answer depends on extrapolating the existing capacity curve, not on gut feeling.

## Extrapolation Rule

Given TTFT p99 values at conc=10, 50, 100, estimate conc=200 using a **linear degradation model** (the simplest that fits observed data):

```
TTFT_p99(conc) ≈ base + k × conc

Where k is derived from the steepest interval:
k = (TTFT_p99(conc=100) - TTFT_p99(conc=50)) / (100 - 50)
```

If the extrapolated TTFT p99 at conc=200 exceeds a **user-acceptable threshold** (typically 5000ms = 5s for interactive applications, 10000ms = 10s for batch), conc=200 is **operationally irrelevant**.

## Worked Example (from this session)

### gpt-oss-120b
| Conc | TTFT p99 |
|------|----------|
| 10 | 978 ms |
| 25 | 1924 ms |
| 50 | 3575 ms |
| 100 | 7310 ms |

Extrapolation to conc=200:
- k = (7310 - 3575) / 50 = **74.7 ms/conc**
- TTFT_p99(200) = 7310 + 74.7 × 100 = **14,780 ms**

**Verdict: Unusable. Users won't wait 15 seconds for the first token.**

### gemma-4-31b-it
| Conc | TTFT p99 |
|------|----------|
| 10 | 381 ms |
| 50 | 1042 ms |
| 100 | 2060 ms |

Extrapolation:
- k = (2060 - 1042) / 50 = **20.4 ms/conc**
- TTFT_p99(200) = 2060 + 20.4 × 100 = **4,100 ms**

**Verdict: Borderline. 4.1s is acceptable for some batch use cases, unacceptable for chat.**

### moonshotai-kimi-k2.6
| Conc | TTFT p99 |
|------|----------|
| 10 | 695 ms |
| 25 | 1178 ms |
| 50 | 1989 ms |
| 100 | 3926 ms |

Extrapolation:
- k = (3926 - 1989) / 50 = **38.7 ms/conc**
- TTFT_p99(200) = 3926 + 38.7 × 100 = **7,796 ms**

**Verdict: Unusable for interactive use.**

## Alternative to Higher Concurrency: Longer Inputs

When conc=100 is already the practical ceiling, the more valuable test is **long-context prefill stress**:

| Test | What it measures | When to use |
|------|-----------------|-------------|
| conc=10→100 | Queueing / scheduling efficiency | Find max parallel users |
| ISL=512 → 1024 → 2048 → 4096 | Memory bandwidth / KV-cache limits | RAG, document analysis, long-context agents |

A model that degrades gracefully at conc=100 but collapses at ISL=2048 has a **memory-bandwidth bottleneck**, not a scheduling bottleneck. The fix is faster memory (HBM3e), not more GPU compute.

## Breakpoint Detection Heuristic

Formally define the "breakpoint" as the highest concurrency where **all three** conditions hold:

1. TTFT p99 < 5000 ms (5 seconds)
2. ITL p99 < 200 ms (readable streaming, ~5 tok/s per user)
3. Output throughput still scales linearly with concurrency (no saturation)

From observed data:

| Model | Breakpoint (conc) | Limiting factor |
|-------|-------------------|-----------------|
| gemma-4-31b-it | ~100 | TTFT ≈ 2s still OK |
| moonshotai-kimi-k2.6 | ~75 | TTFT ≈ 3.5s approaching limit |
| gpt-oss-120b | ~40 | TTFT ≈ 3.5s at conc=50 |
| qwen3.6-27b-nvfp4 | ~40 | TTFT ≈ 3s at conc=50 |

## Operational Recommendation

- Set **hard concurrency limits** at the breakpoint, not at the hardware maximum
- Implement **queueing + load balancing** beyond the breakpoint
- Test **LLM-as-a-Service tiers**:
  - Tier 1 (Premium): conc ≤ 10, guaranteed < 1s TTFT
  - Tier 2 (Standard): conc ≤ 50, guaranteed < 3s TTFT
  - Tier 3 (Batch): conc ≤ 100, best-effort, queueing OK
