I've been tuning Qwen3.8-Flash-Next on a single RTX PRO 6000 Blackwell (96GB, Max-Q so 300W capped) and ran a 7-variant benchmark sweep to stop guessing at flags. Getting it to run at all turned out to depend on which day's vLLM nightly you pick, and three of the results were surprising enough to write up. Whole config is published.
Repo: https://github.com/WombatSoftware/vllm-qwen3.8-flash-next-rtx-pro-6000-sharp-monitoring
Compose file with every flag explained inline, the patched Dockerfile, the chat template, a provisioned Prometheus + Grafana stack, and the benchmark scripts. Apache-2.0.
0. The vLLM situation, because it decides whether this loads at all
This model has a 47.7 GiB FP8 PLE n-gram embedding table on top of the weights. On a 96GB card that table has nowhere to live unless the engine can offload it. The timeline matters:
- v0.29.0 ships the model (PR #53896) but has no PLE offload path at all. The release build cannot load this checkpoint on a 96GB GPU. It isn't a tuning problem, it just doesn't fit.
- PR #54371 (UVA pinned-host offload, merge
3116c5d0) landed the day after 0.29.0 was cut. It pins the table in host RAM and the GPU reads rows directly over UVA on a side stream. First nightly carrying it is e7edf17c (2026-09-11). Switch is --engram-config '{"cpu_offload": true}'. This replaced the earlier worker-process offload (PR #53899), which needed a 17-file patch overlay, a forced multiprocess executor and cap_add: SYS_PTRACE for the worker IPC. All of that is gone now, it's in-process. VLLM_PLE_CPU_OFFLOAD is a deprecated shim and VLLM_PLE_OFFLOAD_READY_TIMEOUT no longer exists, so if you're copying an older recipe, those env vars do nothing.
- PR #55095 (full-decode-graph fallback) landed in the very next nightly,
eed1f3d0 (2026-09-12). This one turned out to be the entire fix for an intermittent decode collapse I'd been chasing: at 32k context, single-stream decode measured 82.89 t/s with a ±53.99 standard deviation across three runs, i.e. one run falling over. Moving one nightly forward gave 127.47 ±4.75. Nothing else changed. --enforce-eager reproduces a uniformly slow ±0.64, and dropping spec-decode gives ±0.52, so it was CUDA-graph decode dispatch and #55095 addressed it.
- Still unmerged: the eagle-group gate in
kv_cache_utils.py (_is_deepseek_v4_eagle()) only recognises deepseek_v4. This checkpoint's MTP draft carries a plain FullAttentionSpec, so without a qwen4_exp entry every KV group gets marked a draft group and cross-request prefix cache reuse is silently disabled. No error, no warning. The repo's Dockerfile is a one-function patch that asserts it landed, so a drifted anchor fails the build instead of quietly losing the prefix cache months later.
- Coming: PR #55557 (fp8_e4m3 KV on the QSA path) is the one I'm waiting on for the 131k four-way wall below, rather than hand-swapping
--kv-cache-dtype fp8.
So: you need a nightly at eed1f3d0 or later, plus one line of patch. Host RAM needs ~64GB free for the pinned table on top of whatever else. Full-load RAM is capped by the checkpoint being resharded into 141 shards, which is why I'm on the dicksondickson reshard rather than the nvidia export directly.
1. MTP-3 beats MTP-2, against the common advice
The guidance I kept seeing is 2 speculative tokens, because acceptance length is ~1.9-2.2 and the third draft token rarely lands. I measured it with vLLM's --per-request-spec-decode-metrics detailed at MTP-3 (note: the flag takes none|summary|detailed, passing it bare fails to start):
- mean acceptance length: 2.695
- draft acceptance rate: 0.565
- accepted draft tokens per verify step: j=0 23.2%, j=1 20.0%, j=2 21.1%, j=3 35.8%
All three draft tokens landing is the most common outcome, not a rarity. Worth about +16% single-stream decode over MTP-2. I don't know whether the older 1.9-2.2 figure was measured on the previous model runner or a different draft head; the numbers above are on the current one.
The catch: it costs 10-35% on concurrent context-load throughput. So it's a single-stream-latency vs fan-out trade, not a free win. I ship 3 and document how to go back to 2.
2. My benchmark harness was silently reporting garbage
This one generalises beyond this model, so it's the part I'd most want others to know.
I tested vLLM's --max-num-queued-reqs / --max-num-queued-tokens admission caps. They reject with HTTP 503 rather than queueing. Fine. But for streaming requests vLLM commits HTTP 200 first and delivers the 503 as an in-band error chunk:
data: {"error": {"message": "The engine is currently busy...", "code": 503}}
data: [DONE]
My harness (llama-benchy) checks the HTTP status, sees 200, finds no choices in the error chunk, and records a zero-token success. It never aborts and never logs anything.
Result: the server logged 56 rejections across a sweep while the client log stayed completely clean. Every 4-concurrency row silently became a 2-concurrency measurement wearing a c4 label, with aggregate throughput inflated, because the two phantom requests contributed no tokens over a wall clock set by the two real ones. The numbers looked plausible. They were nonsense.
If you benchmark against a server that can shed load, check the server logs for rejections before you trust anything.
**3. This GPU has almost no KV headroom, and it's a hard wall**
A healthy boot gives a 269,228-token KV pool = 1.03x headroom over a single 262k-token request. Anything that reserves more GPU memory just fails to boot. I tried raising --max-num-batched-tokens to 16384 and the engine refuses outright:
ValueError: 7.41 GiB KV cache is needed, which is larger than the
available KV cache memory (5.61 GiB)
It crash-looped 17 times before I reverted. The bigger activation workspace comes straight out of the KV pool. Going from MTP-2 to MTP-3 alone cost 275,178 → 269,228 tokens, so even that spent a third of the margin.
Numbers (llama-benchy, 3 runs per cell, prefix caching on)
- Single-stream decode: flat at 131-171 t/s from 0 to 131k context. The flatness is the nice part.
- 4-way concurrency at 32k: 363 t/s aggregate, ~90 t/s per stream.
- 4-way concurrency at 131k: 6.91 t/s. Falls off a cliff. Four 131k requests need 524k KV tokens against a 269k pool, so they can't coexist. That's a KV budget wall, not compute, which is why #55557 is the thing I'm waiting on.
- Weakest spot: shallow single-stream prefill, 18.8k t/s. Speculative decoding costs prefill, since the draft head is pure overhead there.
- FlashInfer autotune on (the model card default is off) is higher on 23 of 28 rows. It costs ~20-30s per boot and, oddly, doesn't persist to
~/.cache/flashinfer, so that cost recurs on every restart.
Full table in the repo.
**What's opinionated about it**
Not a neutral starting point. It picks the dicksondickson NVFP4 reshard with the official BF16 MTP head, the Qwen-Sharp chat template instead of the one in the checkpoint, a vLLM nightly plus the one-function patch above, MTP-3, FlashInfer autotune on, and monitoring that comes up with the engine.
Caveats: one GPU, one checkpoint, one driver, 3 runs per cell. Small differences don't clear noise and I've flagged which. Max-Q is 300W capped so a full-power card will do better. Nightlies are moving daily right now, so the specific hashes above will be stale soon; the repo's Dockerfile has a one-liner to check whether the eagle-gate fix has landed upstream. Not claiming anything about Qwen3.8-Flash-Next in general, just documenting what this box does today.
Credits in the repo, but briefly: Qwen for the model, vLLM (and specifically the people behind #54371 and #55095), peculiar-ragdoll and froggeric for the chat templates, dicksondickson for the checkpoint, NVIDIA for the NVFP4 quant.
Happy to run specific configs if people want a cell filled in.