vLLM vs llama.cpp: do you actually need vLLM to self-host?

A split scale weighing a single portable binary against a multi-GPU rack, illustrating the llama.cpp versus vLLM serving-engine tradeoff.

The vLLM vs llama.cpp choice is a concurrency question, not a seniority ladder. llama.cpp is enough, and faster for a single request, until sustained load crosses roughly five or six concurrent users.

TLDR

The vLLM vs llama.cpp choice is a concurrency question, not a seniority ladder. llama.cpp is enough, and actually faster for a single request, until sustained load crosses roughly five or six concurrent users. Above that line vLLM's continuous batching earns its extra operational cost. Pick the engine for the load you have, not the one that sounds serious.

I keep meeting teams who treat the serving engine like a rite of passage. They start on llama.cpp or Ollama, it works fine, and then someone in a planning meeting says the quiet part out loud: “sure, but that’s not really production. We need vLLM.” The unspoken belief underneath that sentence is that llama.cpp is the toy and vLLM is the grown-up, and that moving a self-hosted model to production means moving off the first and onto the second.

Here is the line that quietly breaks the hierarchy. Ollama shipped v0.31.2 on July 8, and buried in the release notes, right next to the flash-attention fix for older NVIDIA cards, is this: it “Updated the MLX and llama.cpp engines.” llama.cpp is not the thing you graduate away from. It is the engine running underneath the easy button that half the market already uses in production.


Why vLLM’s throughput numbers make the choice look obvious

The myth earns its believers honestly, because the benchmarks that feed it are real and lopsided. Once concurrent users climb past five or six, vLLM pulls ahead sharply. A concurrent stress test written up by D-Central in June clocked vLLM at roughly 793 aggregate tokens per second against about 41 for a single-stream path under the same simultaneous load. That is not a rounding difference. That is a different category of machine.

The reason is architectural, not marketing. vLLM’s PagedAttention and continuous batching are built to keep an expensive GPU saturated while dozens of requests overlap. If your mental model is “more throughput is strictly better,” vLLM wins every slide in the deck, and it deserves to.

~5-6
concurrent users: the load where vLLM's batching starts to pull decisively ahead of a single-stream engine (D-Central, June 2026)

What the benchmarks show once you count concurrent users

Now the part that never makes the slide. For a single request, the engine everyone calls a toy is often the faster one. Markaicode’s July benchmark on an A100 80GB ran QwQ-32B through both: llama.cpp finished in 1 minute 42.7 seconds, vLLM in 2 minutes 7.4 seconds. Continuous batching is overhead you agree to pay so the machine can serve many requests at once. With exactly one request in flight, there is nothing to batch, and that overhead is just tax.

Then there is the format trap, which is where a lot of “we moved to vLLM and it got slower” stories actually come from.

"when GGUF weights are loaded inside vLLM, throughput (93 tok/s) trails vLLM's native quantization paths like Marlin-AWQ (741 tok/s) by roughly 8x in this test."

Markaicode, July 2026

If a team is committed to GGUF weights, llama.cpp is the home field where GGUF is native and tuned. Dropping those same weights into vLLM throws away most of what vLLM is good at and keeps all of its operational weight. The honest other side holds too: run the right native format at real concurrency on a GPU and vLLM wins by multiples, not percentages. Both facts are true at the same time, which is exactly why the blanket “vLLM is production, llama.cpp is not” framing falls apart.

Same Models, Different Load: Who Wins
Scenariollama.cpp pathvLLM path
Single request (QwQ-32B, A100)1m42.7s2m7.4s
Committed to GGUF weightsnative, tuned93 tok/s (8x slower than native)
8+ concurrent on a GPU~41 tok/s aggregate~793 tok/s aggregate

For a single request, the engine everyone calls a toy finished faster than the one everyone calls production.


llama.cpp vs vLLM is a concurrency line, not a seniority ladder

Here is the mental model that survives contact with the benchmarks. The serving engine is a match to the shape of the traffic, not a badge of how serious the team is. One user at a time, CPU or Apple Silicon or mixed hardware, or a portable single binary that just runs on whatever box is available: that is llama.cpp’s territory, and Red Hat’s own engineering writeup lands in the same place. Sustained multi-user load on a GPU, an OpenAI-compatible endpoint, Kubernetes-native scaling: that is where vLLM stops being overhead and starts being the point.

The fresh release this week is a clean test case. Tencent put out Hy3 on July 6, an open 295B mixture-of-experts model with 21B active parameters, a 256K context window, and Apache 2.0 weights. That shape, large memory footprint but low active compute per token, is precisely where the engine question bites. Both engines can plausibly serve it. The deciding factor is not which one is “real.” It is how many people hit the endpoint at the same moment.

Key Insight

The right engine is set by concurrency and hardware, not by how production-grade the tool sounds. llama.cpp below the line, vLLM above it, and the line is roughly where a single GPU stops keeping up with simultaneous requests.


What to run this week for your actual load

Count the real number first. Not the number of registered users, the number of requests genuinely in flight at once during a busy minute. For a lot of internal tools, batch jobs, and single-founder prototypes, that number is one, and the whole vLLM migration is solving a problem the traffic does not have.

The cost backdrop reinforces the point. GetDeploying’s tracker had the average H100 at $3.41 per hour on July 9, with on-demand rates up about 14 percent over the past year. The GPU a team rents to justify vLLM’s throughput keeps getting more expensive, so paying for batching that mostly sits idle is a worse deal every quarter. Most healthy setups I see run both without drama: llama.cpp or Ollama for development, low-concurrency internal use, and edge boxes, then vLLM the moment a specific workload proves it lives above the concurrency line. That is not indecision. That is matching the tool to the traffic, which is the only version of this question that has ever had a real answer.

Sources

  1. vLLM vs llama.cpp (2026): What Official Docs and Public Benchmarks Actually Show - Markaicode, 2026-07-03
  2. Ollama vs vLLM vs llama.cpp: Local Inference Server Comparison (2026) - D-Central, 2026-06-15
  3. llama.cpp vs. vLLM: Choosing the right local LLM inference engine - Red Hat Developer, 2026-06-15
  4. Ollama Release Notes (v0.31.2) - Releasebot / Ollama, 2026-07-08
  5. NVIDIA H100 Cloud GPU Pricing (live tracker) - GetDeploying, 2026-07-09
  6. Tencent Releases Hy3: Open 295B MoE (21B active, 256K context) - MarkTechPost, 2026-07-06

Back to all insights