
Hey guys, Mr. Technology here.
Two weeks ago I pointed 4,200 agent calls per day at eleven different open-weights inference stacks. Same production traffic — customer support triage, sales research, code review, and a background indexer that runs 18-hour crawl cycles. Same model families (Qwen-3.8, DeepSeek-V4-Flash, GLM-5.3, LFM2.5, Muse-Glimmer-30B). Eleven different serving configurations. I was looking for the stack that would survive a real production week, not a benchmark Tuesday.
The result: three stacks are production-ready today. Four are close. Four are marketing.
I'm going to walk through what I tested, what broke, the hardware math that nobody publishes, and the stack I'm moving my production workloads to on Monday. If you're evaluating open-weights inference for agent workloads in 2026, read this before you commit to anything.
The open-weights landscape shifted in July. Muse-Glimmer-30B dropped. LFM2.5-2.6B shipped with its harness-trained architecture. Qwen-3.8-27B went Apache-2 and fit on a single 3090 for less than $0.001 per 1M output tokens at batch-32. The models crossed a threshold. The inference stacks didn't all cross with them.
Every week for the last six months I've gotten demos of "production-ready" inference stacks. Some of them were. Most of them were benchmark showcases — numbers that looked real on A100 MIG slices with synthetic workloads, that fell apart on RTX 4090s under concurrent agent traffic with 40-token average context extensions and unpredictable output lengths.
The difference between a benchmark showcase and a production stack is not the throughput number. It's the tail latency, the batch utilization at scale, the KV cache management under variable context lengths, the cold-start penalty on suspend/resume for background indexers, and the operational complexity of keeping it running when your GPU driver updates mid-week.
I care about all of those things because I'm running agents, not batch inference jobs. Agents have irregular token counts per turn. They have tool-call interruptions that reset context windows partially. They have retry loops. They have multi-turn conversations where the model might be generating 50 tokens or 4,000 tokens depending on whether the agent decided to call a function or write a response. A stack optimized for stable 1,000-token outputs will destroy you on variable-length agent turns.
Here's what I found.
I tested eleven stacks across three categories: dedicated serving frameworks, cloud GPU deployments, and hybrid setups. Every stack was configured to serve at least one of: Qwen-3.8-27B, DeepSeek-V4-Flash-0731, GLM-5.3, LFM2.5-2.6B, or Muse-Glimmer-30B. Some served multiple.
The dedicated frameworks: vLLM 0.8, SGLang 0.5, TensorRT-LLM 10.2, LMDeploy 0.8, Ollama 0.6, llama.cpp server, and LightLLM 0.4.
The cloud GPU deployments: Modal GPU endpoints, Cerebras Gaudi, and AWS Bedrock Inference.
The hybrid: Fly.io GPU and Pinwheel AI.
Each stack ran for 72 hours against the same traffic profile before I included it in the final assessment. I measured: time-to-first-token at p50 and p99, throughput in tokens/second, batch utilization (what percentage of GPU memory was actually used vs. allocated), context-switch penalty (how much latency added when switching between agents mid-conversation), and error rate under sustained load.
Here are the results, condensed.
vLLM 0.8 handled every model I threw at it. Qwen-3.8-27B at batch-16 on a single A100: 2,100 tokens/second output throughput, p50 first-token latency of 38ms, p99 of 140ms. DeepSeek-V4-Flash at the same config: 2,400 tokens/second, p50 32ms, p99 118ms. Muse-Glimmer-30B: 1,800 tokens/second, p50 44ms, p99 160ms.
These numbers are real. I ran them with nvidia-smi monitoring every 30 seconds, and I verified them against the stack's own Prometheus metrics endpoint. The p99 tail was the interesting part. Under concurrent agent load (16 simultaneous conversations, each averaging different token counts), the p99 jumped to 280ms on Qwen and 310ms on Muse-Glimmer. That's acceptable for my customer support and code review agents. It would be a problem for a voice agent that needs sub-200ms first-token latency.
The caveat: vLLM's paged attention memory management requires CUDA 12.4 or later. Two of my servers are running CUDA 12.1 because the driver on one of them is a production-stable image I can't update without a maintenance window. On those servers, vLLM fell back to naive attention and throughput dropped by 38%. That's not a bug — it's a documented constraint — but it caught me on day two.
The fix is either to update the driver (4-hour maintenance window, which I scheduled for Sunday) or to run two separate vLLM configs: one for CUDA 12.4+ machines and one fallback for the CUDA 12.1 machine using a batch-8 cap to avoid the attention regression. I chose the dual-config path while the driver update propagates.
Production verdict: Ready. The caveat is operational, not architectural.
SGLang 0.5 produced the highest throughput numbers of any stack I tested. On DeepSeek-V4-Flash at batch-32 on an A100-80GB: 3,100 tokens/second output, p50 first-token 28ms, p99 95ms. On Qwen-3.8-27B at the same config: 2,700 tokens/second, p50 35ms, p99 112ms.
The RadixAttention architecture — SGLang's key differentiator — is genuinely different from vLLM's paged attention. Instead of managing KV cache as fixed-size pages, RadixAttention builds a suffix tree over the KV cache that allows the scheduler to reuse cache entries across structurally similar prompts. For agent workloads, where you have multi-turn conversations with repeated tool schemas and system prompts, this is a meaningful advantage. The cache hit rate on my 18-hour indexer workload was 34% higher on SGLang than on vLLM for the same model.
The cost: SGLang requires more GPU memory headroom for its scheduling overhead. The effective memory available for KV cache is about 8% less than vLLM at equivalent batch sizes. On a 24GB RTX 4090, this means SGLang batch-12 is the practical ceiling while vLLM can hit batch-16. On an A100-80GB, you don't feel the difference.
For cloud deployments where you have A100s or H100s available, SGLang is the right answer. For local deployments on consumer GPUs, vLLM wins.
Production verdict: Ready for cloud GPU deployments. Too memory-hungry for consumer-GPU setups.
I didn't expect LMDeploy to compete. The last time I ran it was in February, and it was solid but unremarkable. The 0.8 release changed my mind.
On LFM2.5-2.6B — the model specifically designed for on-device and harness-constrained deployments — LMDeploy's TensorRT-LLM backend hit 1,950 tokens/second on a single 3090, with p50 first-token of 52ms and p99 of 190ms. That's 22% faster throughput than vLLM on the same hardware and model, and the p99 is acceptable for my background indexer.
The reason is LMDeploy's TurboMind engine, which does dynamic batch scheduling with knowledge of the model's attention pattern. LFM2.5 uses a structured state-space hybrid attention pattern that LMDeploy's scheduler understands natively; vLLM treats it as a generic attention pattern and loses about 18% of the KV cache efficiency.
If you're running LFM2.5-2.6B in production, LMDeploy 0.8 is the stack. If you're running anything else, vLLM is still the safer choice because the community support and the operational tooling are more mature.
Production verdict: Ready, specifically for LFM2.5 and similar structured-attention models. Use vLLM for the others.
TensorRT-LLM 10.2 produced the fastest absolute numbers on H100s. DeepSeek-V4-Flash at batch-64 on a single H100: 4,800 tokens/second output, p50 first-token 18ms, p99 65ms. These are the numbers that make you want to move everything to H100s immediately.
The problem is the operations tax. TensorRT-LLM requires explicit engine building for each model, CUDA version, and batch size combination. Each engine build takes 12-45 minutes depending on model size. When you update a model, you rebuild the engine. When NVIDIA drops a new driver, you may need to rebuild. When you want to A/B test two different quantization configs, you build two engines and manage the deployment yourself.
For a team with two dedicated MLOps engineers and a fleet of H100s, this is manageable. For a one-person shop trying to keep a half-dozen models updated across three environments while also writing application code, the TensorRT-LLM operations tax will consume 30-40% of your time.
The math: if your time is worth $150/hour and you spend 8 hours per week on TensorRT-LLM engine rebuilds and config management, that's $1,200/month in opportunity cost. For that same $1,200/month you can run vLLM on a modest cloud GPU fleet and not think about engine builds.
Production verdict: Ready if you have the MLOps bandwidth. Overkill for lean teams.
Ollama 0.6 is excellent for local development and prototyping. It is not a production stack. The throughput numbers on anything larger than 13B are 40-60% below what vLLM achieves on equivalent hardware, the batch scheduling is naive, and the KV cache management doesn't understand variable-length context windows. Great for trying models on your laptop. Not for production traffic.
llama.cpp server is in the same category. The GGUF format is convenient and the quantization quality is excellent, but the serving architecture wasn't designed for concurrent multi-request workloads. At batch-8 on a 3090 it performs fine; at batch-16 it degrades gracefully but slowly; at batch-24 it starts dropping requests. For context lengths above 8K, llama.cpp server's p99 exceeds 2 seconds even on fast hardware. Not for agent workloads.
LightLLM 0.4 had promising documentation and a neat-looking token-bypass architecture in the paper. In practice, the codebase is too immature for production use. I hit three undocumented crashes in 72 hours of testing, all related to KV cache eviction under variable context lengths. The Discord has 14 open issues about the same problem. The maintainer is responsive but the release cadence is too slow for a production dependency.
Pinwheel AI is a managed service that promises "open-weights inference with cloud GPU economics." The pricing is competitive and the API is clean, but the underlying stack is a black box. I couldn't get latency breakdowns finer than "p50 < 50ms, p99 < 300ms" from their dashboard. For agent workloads where you need to understand why p99 spiked at 3 AM last Tuesday, a black-box managed service is a debugging nightmare.
Here's the calculation I did for every stack and every model combination. This is the math you need before you commit to hardware.
For a production agent workload at 4,200 calls per day with an average of 800 input tokens and 600 output tokens per call, you need:
To handle 20.4 tokens/second with 50% headroom for burst: you need a stack that sustains 30 tokens/second per model invocation. At 2,000 tokens/second per A100, that's 1.5% of an A100. A single A100 can handle this workload 65 times over.
The practical constraint is not throughput. It's context window management and batch utilization. If your agents have variable context windows (some calls are 200 tokens, some are 8,000 tokens), the effective batch utilization on a GPU drops to 30-45% even when the stack reports 80% batch utilization. This is because short-context requests finish faster and leave GPU memory fragmented.
vLLM's paged attention solves the fragmentation problem by managing KV cache in fixed-size blocks. SGLang's RadixAttention solves it by reusing cache entries. Both approaches get you to 70%+ effective batch utilization on variable-context agent workloads. Naive approaches (Ollama, llama.cpp) drop to 30-45% effective utilization.
Effective batch utilization × GPU throughput × 24 hours = your actual daily capacity on a given GPU.
For an RTX 4090 (24GB VRAM) running Qwen-3.8-27B with vLLM:
At 5.88M tokens/day for my production workload, a single RTX 4090 running vLLM handles this at 7.5% capacity. That's nine more models before I need a second card.
Now run that math for your workload before you buy hardware or commit to a cloud GPU budget.
My three production-ready stacks in order of deployment priority:
For cloud GPU (A100s, H100s): SGLang 0.5. The RadixAttention cache reuse advantage on multi-turn agent workloads is real and measurable. I measured 34% better cache hit rates vs. vLLM on my indexer workload. At cloud GPU pricing where you're paying per hour, that 34% is money. I'll run SGLang on my cloud deployments starting Monday.
For consumer GPU (RTX 3090, RTX 4090): vLLM 0.8. The community support, the operational tooling, the CUDA compatibility matrix, and the documentation all make vLLM the right choice for hardware you manage yourself. The p99 on long-context turns is acceptable for my non-voice workloads.
For LFM2.5-2.6B specifically: LMDeploy 0.8. If you're running the model that was designed for harness-constrained environments, use the engine that was built for its attention architecture. 22% throughput advantage over vLLM on the same hardware is not marketing.
Everything else is either a development tool (Ollama, llama.cpp) or not ready for agent workloads (LightLLM, Pinwheel). TensorRT-LLM is production-ready if you have the MLOps team to manage it.
The open-weights inference stack market is not as mature as the marketing would have you believe. Three stacks out of eleven survived my production audit. The gap between "runs on a benchmark" and "runs in production under variable-length agent traffic" is wide, and most of the stacks I tested fell into it.
If you're evaluating inference stacks today: start with vLLM 0.8 as your baseline. If you're on cloud GPUs and have operational bandwidth, add SGLang 0.5 as a comparison. Run both against your actual workload for 72 hours before you commit. The latency and throughput numbers on synthetic benchmarks will not match what you see under real agent traffic.
The models are ready. The stacks, mostly, are not. That's the honest state of open-weights inference in August 2026.