Today started with a very reasonable engineering plan:
Run
Qwen/Qwen3.6-27B-FP8on SGLang.
Simple.
Clean.
Responsible.
Naturally, within minutes, I had rented the wrong GPU.
Act 1: The A40 Incident
I started with an A40.
On paper, this made sense if you squint hard enough. It has 48 GB of VRAM. It is available. It is not outrageously expensive. It looks like the kind of GPU you rent when you want to “just test something quickly.”
Unfortunately, the thing I wanted to test was FP8.
The A40 is Ampere.
Ampere is not where this story belongs.
So the first lesson arrived immediately:
VRAM is not a personality.
Architecture matters.
The A40 was terminated.
No ceremony. No farewell message. Just goodbye.
Act 2: Fine, We’re Doing Blackwell
After briefly pretending I was going to be practical, I rented the machine I should have rented in the first place:
GPU: RTX PRO 6000 Blackwell Server Edition
VRAM: 96 GB
RAM: 140 GB
vCPU: 16
Persistent disk: 120 GB
Container disk: 80 GB
Now we were speaking the right language.
This was no longer “can I squeeze this model into a GPU and pray?”
This was:
Let’s see if a single Blackwell card can become a real inference lane.
The target stack:
Model: Qwen/Qwen3.6-27B-FP8
Runtime: SGLang
GPU: RTX PRO 6000 Blackwell
API: OpenAI-compatible
Beautiful.
Then CUDA showed up with a chair.
Act 3: CUDA Userspace Betrayal
The first container image I used was:
runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404
It looked fine.
PyTorch saw the GPU:
NVIDIA RTX PRO 6000 Blackwell Server Edition
The driver reported CUDA 13 support.
Everything seemed okay.
Then SGLang said:
Failed to get device capability: SM 12.x requires CUDA >= 12.9.
And there it was.
The machine had a CUDA 13-capable driver, but the container userspace/toolkit was CUDA 12.8.
That is the kind of error that makes you stare at the terminal like it owes you money.
The fix was to stop being clever and use the official SGLang CUDA 13 image:
lmsysorg/sglang:dev-cu13
That was the correct move.
The container initially needed a boring foreground command to stay alive, so I used:
sleep infinity
Not glamorous.
Extremely effective.
Act 4: The Boring Launch That Proved the Stack
Inside the working container, I set the Hugging Face cache to the persistent volume:
export HF_HOME=/workspace/hf-cache
export HF_XET_HIGH_PERFORMANCE=1
Then I launched the model with the most basic command possible:
python -m sglang.launch_server \
--model-path Qwen/Qwen3.6-27B-FP8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code
This was not the final performance config.
This was the “does the thing even boot?” config.
And it did.
The logs said exactly what I wanted to see:
Detected fp8 checkpoint.
Load weight begin. avail mem=94.27 GB
Auto-detected template features:
reasoning_parser=qwen3
tool_call_parser=qwen3_coder
Uvicorn running on http://0.0.0.0:30000
At this point, the model was alive.
But alive is not the same thing as fast.
That came next.
Act 5: The Actual Config That Made It Fly
The basic launch proved compatibility.
The tuned config made it stupid.
This was the real serving command:
sglang serve \
--model-path Qwen/Qwen3.6-27B-FP8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--reasoning-parser qwen3 \
--tool-call-parser qwen3_coder \
--speculative-algorithm EAGLE \
--speculative-num-steps 3 \
--speculative-eagle-topk 1 \
--speculative-num-draft-tokens 4 \
--mamba-scheduler-strategy extra_buffer \
--page-size 64 \
--chunked-prefill-size 16384 \
--max-prefill-tokens 32768 \
--mem-fraction-static 0.75 \
--enable-cache-report
This is the important distinction.
The default launch got Qwen running.
This config made it feel production-shaped.
The explicit Qwen parsers aligned SGLang with the model’s reasoning and tool-call format. EAGLE speculative decoding helped the decode path. Chunked prefill and the scheduler settings mattered because the workload was not a cute 512-token prompt. It was a large, repeated, agent-shaped prompt.
This is where the experiment stopped feeling like:
“Cool, the model runs.”
And started feeling like:
“Wait. This might actually serve agents.”
Act 6: The First Real Benchmark
The benchmark prompt was intentionally obnoxious.
I repeated a small reasoning problem 400 times to create a roughly 20k-token prompt:
python tools/sglang_bench.py \
--runs 1 \
--prompt-repeat 400 \
--max-tokens 8000
The shape of the result:
Prompt tokens: ~19,609
Completion tokens: ~2,300–2,500
TTFT: ~1.3–2.5s
Decode throughput: ~79–82 tok/s
End-to-end: ~30–33s
That was the first “oh no, this is real” moment.
A 20k-token prompt.
Thinking enabled.
First token in around 1–2.5 seconds.
Sustained decode around 80 tokens/sec.
That is not a toy benchmark anymore. That is very close to the shape of a real agent request.
Act 7: Five Terminals, Then Thirteen, Then Bad Decisions
At first I ran one request.
Then several.
Then five terminals at once.
It still held.
Then thirteen concurrent requests.
Still held.
The SGLang logs were the fun part:
cuda graph: True
accept len: ~3
accept rate: ~0.7+
gen throughput: ~750–830 tok/s aggregate
That is where the test stopped being about Qwen alone.
This became a scheduler test.
SGLang was doing real work here: batching, scheduling, speculative decoding, and keeping the GPU busy without the whole system turning into soup.
Act 8: The 50-User Hunger Games
At some point, incremental testing lost the argument.
So I ran:
python tools/sglang_bench.py \
--users 50 \
--requests-per-user 1 \
--prompt-repeat 400 \
--max-tokens 8000 \
--timeout 600
This fired 50 long-context requests at the server.
Each request had roughly:
~19.6k prompt tokens
~2k–3k completion tokens
thinking enabled
streaming enabled
The result:
successful_requests=50
failed_requests=0
wall_time=206.105s
Aggregate Tokens
prompt=980450
completion=120586
total=1101036
Aggregate Throughput
prompt_per_wall=4757.04 tok/s
completion_per_wall=585.07 tok/s
total_per_wall=5342.11 tok/s
Per-Request Distribution
ttft_sec: min=1.311 median=1.905 p90=3.268 max=10.944
e2e_sec: min=28.256 median=42.128 p90=52.550 max=59.781
completion_decode_tps: min=47.512 median=60.833 p90=64.546 max=78.717
The headline:
50 requests.
0 failures.
The median TTFT stayed under 2 seconds.
The median decode throughput was around 60 tokens/sec.
One request had a TTFT outlier around 11 seconds, which is exactly the kind of thing a real load test should reveal.
But the system did not collapse.
No dramatic death spiral.
No wall of timeouts.
No “please reduce your expectations” message from the GPU.
Just throughput.
Act 9: Important Honesty Break
The 50-user test was useful, but I would not oversell it as a perfect 50-simultaneous-client benchmark yet.
The benchmark script uses blocking urllib calls wrapped in asyncio.to_thread().
That means it works well as a practical chaos/load test, but Python thread scheduling can still affect how perfectly simultaneous the requests are.
Before turning this into a formal benchmark claim, I want a true async streaming client using something like httpx.AsyncClient.
The next harness should record:
virtual user scheduled time
actual request send time
first byte
first token
end of stream
usage tokens
server queue behavior
Still, the result is extremely useful.
It showed that this stack can handle a nasty burst of large-context, thinking-enabled requests without falling apart.
Act 10: The 1000-User Crime Scene
Then I did the unreasonable thing.
python tools/sglang_bench.py \
--users 1000 \
--requests-per-user 1 \
--prompt-repeat 400 \
--max-tokens 8000 \
--timeout 600
This was not a benchmark.
This was violence.
A thousand requests.
Each with around 20k prompt tokens.
That is about 19.6 million prompt tokens thrown at one GPU.
SGLang did not politely ask me to stop. It simply showed me the wall:
#running-req: 13
#queue-req: 984
#pending-token: 19285959
There it was.
For this workload, the active running set was around 13 requests.
The rest queued.
That is actually a great result, because now I know the shape of the bottleneck.
The server did not mysteriously explode. It exposed its scheduling behavior.
But the most important line was this:
#cached-token: 19584
#new-token: 64
That line is the entire production story.
The prompt was mostly repeated across requests. SGLang reused the prefix. It did not recompute the entire ~19.6k-token prompt from scratch every time.
That is not a benchmark trick.
That is exactly what real agent traffic often looks like:
same system prompt
same product instructions
same tool descriptions
same safety rules
same app context
different user request
Prefix caching is not just a performance optimization.
For agent systems, prefix caching can be the difference between “this is impossible” and “this is a production lane.”
Act 11: Can This Replace GLM 4.7?
Not proven yet.
This test proves the serving side is real.
It does not prove the model quality is good enough.
For my use case, replacing GLM 4.7 is not about whether Qwen can answer a math prompt. It has to survive actual agent work:
tool-call correctness
JSON/schema validity
long-context instruction retention
repair behavior after failed tools
multi-step planning
page/code generation quality
cost per successful task
The scary failure mode is not obvious stupidity.
The scary failure mode is almost-good-enough behavior.
A model can look fast, sound smart, and still make slightly more tool mistakes. In agent systems, a tiny quality regression can erase an infrastructure win.
So the next real test is:
GLM 4.7 production baseline
vs
Qwen3.6-27B-FP8 on SGLang
Same harness.
Same prompts.
Same tool traces.
Same scoring.
Same production tasks.
Only then can I say whether it replaces GLM 4.7.
What I Actually Learned
1. Do not rent architecture by VRAM alone
The A40 had VRAM.
It was still the wrong GPU.
For official FP8 inference, architecture matters.
2. Blackwell wants the right CUDA userspace
The driver can be fine. PyTorch can see the GPU. SGLang can still complain if the container userspace is wrong.
Use the right image.
In this case:
lmsysorg/sglang:dev-cu13
3. The boring launch is only the beginning
The basic launch proved the model could run.
The tuned config produced the real performance.
Production inference is not just:
load model
pray
It is:
model format
runtime
scheduler
speculative decoding
cache behavior
memory layout
workload shape
All of those have to line up.
4. SGLang’s prefix cache is a big deal
The 1000-user chaos test showed:
#cached-token: 19584
#new-token: 64
That is the line I care about most.
Agent workloads repeat huge prefixes constantly. If the runtime can exploit that, the economics change.
5. One RTX PRO 6000 Blackwell is not a toy
At around $1,500/month, this is not “cheap” in the casual sense.
But if it replaces enough API spend, gives predictable latency, avoids rate limits, and supports production agent workloads, it becomes a serious infrastructure option.
The question is not:
Is $1,500 cheap?
The question is:
How many successful agent tasks per month can this box serve compared to managed API spend?
That is the real math.
Final Take
This started as a bad A40 rental.
It ended with:
Qwen/Qwen3.6-27B-FP8
SGLang
RTX PRO 6000 Blackwell
CUDA 13
EAGLE speculative decoding
prefix caching
50-request chaos test
0 failures
The serving side is no longer theoretical.
The model still has to prove itself against GLM 4.7 on real agent tasks.
But as an inference stack?
This thing is alive.
And it is way more serious than I expected when I typed the first command.








