Pick your serving engine on a throughput benchmark and you will optimise the one number your agents never exercise. A chat benchmark sends fresh prompts to a fixed batch; an agent sends the same prompt back twenty times with a few hundred tokens appended, so the work is overwhelmingly prefill of text the GPU has already seen. Three things decide whether that work happens twice — what the KV cache is keyed on, whether constrained decoding survives a full batch, and how long the build step takes — and only one of the four engines below was designed with all three in mind.
At a glance
Four projects that all serve open-weight models over an HTTP endpoint, and share almost nothing else about how they get there.
| Project | Since | Licence | Deployment shape |
|---|---|---|---|
| vLLM | Feb 2023 | Apache-2.0 | Python server, one process per GPU group; the default fleet choice. |
| SGLang | Jan 2024 | Apache-2.0 | Python server, same shape as vLLM; built around a prefix-sharing cache. |
| TensorRT-LLM | Aug 2023 | NVIDIA terms | Compile an engine for a specific GPU and precision, then serve it. |
| llama.cpp | Mar 2023 | MIT | One C++ binary and one GGUF file; laptop to single server. |
Both Python servers ship at a pace that makes any version-specific claim stale within a month — vLLM cut v0.26.0 on 27 July 2026 with 411 commits from 212 contributors, SGLang cut v0.5.16 two days earlier with 574 pull requests from 169. Treat feature-parity gaps as temporary and architectural commitments as permanent, because only the second kind survives a release cycle.
vLLM — the default, and mostly deservedly
PagedAttention, and what it bought
vLLM's original contribution was to stop treating the KV cache as one contiguous allocation per sequence. It splits the cache into fixed-size blocks and manages them the way an operating system manages virtual memory pages, which drops fragmentation close to zero and lets a batch pack tightly. That is why vLLM's throughput advantage over naive serving was large enough in 2023 to end the argument, and why every engine here now does some version of the same thing.
The ecosystem is the actual moat
Three years of being the default produced the thing that is genuinely hard to replicate: Kubernetes operators, autoscalers, prefix-aware routers, observability integrations, and a model-support surface that usually has a new architecture working within days of release. It also runs on more silicon than anything else in its class — CUDA, ROCm, Intel XPU and TPU — which matters more than it looks when your capacity plan depends on whatever GPUs you can actually get.
Where it is weakest
Structured output. vLLM defaults to XGrammar for guided decoding, and the constraint mask is computed on the critical path; third-party measurements through 2026 have repeatedly shown throughput degrading once guided decoding is on and the batch grows past single digits. For a chatbot that is a footnote. For an agent, where every tool call is a constrained generation, it is the common case.
SGLang — the one built for the shape agents actually make
RadixAttention: the cache knows about prefixes
SGLang stores the KV cache in a radix tree keyed on the token prefix rather than in flat hashed blocks. The consequence is not a marginally better hit rate — it is a different capability. Two requests that share their first forty thousand tokens share that computation automatically, without anyone declaring a session, tagging a cache key, or routing them together. For a fleet of agents running the same system prompt, the same tool definitions and the same retrieved corpus, that describes essentially all of the input.
Constrained decoding that does not stall the batch
SGLang overlaps grammar-mask computation with the GPU step instead of blocking on it, which is the direct answer to vLLM's weakest axis. If your workload is mostly tool calls and JSON, this is the difference that shows up in your latency percentiles rather than in a benchmark table.
The cost of being second
A third of vLLM's stars, a smaller operator and tooling ecosystem, and fewer people who have hit your bug before. Third-party H100 benchmarks in 2026 put SGLang roughly 15–30% ahead of vLLM on shared-prefix workloads; treat that band as directional, since it moves with the model, the batch and which fortnight the benchmark was run.
TensorRT-LLM — fastest, if you can pay the build
Compilation is the whole trade
TensorRT-LLM does not interpret a model graph at runtime. It compiles the model into an engine tuned to one GPU architecture and one precision, which is how it posts the fastest absolute numbers on NVIDIA hardware. The price is a build step measured in tens of minutes per combination of model, GPU and precision, and a rebuild whenever any of those change.
What that does to your operations
Every deployment property downstream inherits the compile step. Mixed fleets need an engine per GPU type. Trying a new quantisation is a build, not a flag. Rolling back a model version means having kept the old engine artifact. If you run one model on one homogeneous NVIDIA fleet at high volume, that is a fixed cost you amortise happily; if you are still moving between models every few weeks, it is a tax on exactly the thing you do most.
NVIDIA-only, by design
This is not an oversight to be fixed. The performance comes from compiling to specific NVIDIA kernels, so hardware portability is the thing being traded away. Take it as a deliberate bet on a vendor, and price the lock-in on purpose rather than discovering it during a capacity crunch.
llama.cpp — the one that is not competing
A different problem, solved unusually well
llama.cpp is the most-starred project here by a wide margin and the least relevant to a serving fleet, because it was built to run a model on one machine you own — CPU, Apple Silicon, Vulkan, ROCm or CUDA — from a single quantised GGUF file with no Python and no CUDA toolchain. That is why it has 122,000 stars and why it appears in almost no production agent fleets.
Where it wins outright
Anything on the developer's machine, anything in an air-gapped or edge deployment, anything where the model must ship inside the product. It also has the shortest distance from zero to a serving endpoint of anything in this comparison: one binary, one file, an OpenAI-compatible server, and GBNF grammars for constrained output.
Where it stops
Multi-tenant concurrency. The server keeps prompt caches per slot and can reuse a common prefix, but it is designed around a handful of slots on one box rather than hundreds of concurrent sequences across a fleet. Running an agent workload on it is not wrong — it is a category error that shows up as a queue.
The three axes that actually decide it
1. Prefix reuse — and it is a routing problem, not an engine one
SGLang's radix tree makes overlap automatic, vLLM's content-hashed blocks make it available, TensorRT-LLM's reuse is bound to the engine you built, and llama.cpp's is bound to one process. But that ranking evaporates the moment you put more than one replica behind a load balancer, because none of them can reuse a cache they were never sent.
This is the finding that should reorder most migration plans. Teams routinely spend a quarter moving between engines to chase a 20% throughput difference while running round-robin balancing that discards a large fraction of their prefix cache — a difference measured in multiples, fixed by a routing config. Measure your own prefix-cache hit rate before you compare anyone's benchmark, and if it is below about 80% on agent traffic, the engine is not your problem.
2. Constrained decoding, at the batch size you actually run
Every engine here supports grammar-constrained output; the differences appear only under concurrency. SGLang overlaps mask computation with the GPU step, vLLM computes it on the critical path with XGrammar as the default backend, TensorRT-LLM supports it but has it less exercised in the open, and llama.cpp's GBNF is excellent for one stream and not the point at a hundred. Since an agent emits a constrained generation on every single tool call, this axis is load-bearing for agents in a way it simply is not for chat — and it is the axis most comparison posts omit entirely, because their benchmark ran unconstrained.
3. What the setup step costs you, repeatedly
llama.cpp gets you serving in a minute, the two Python servers in an afternoon of dependency work, and TensorRT-LLM after a compile per model-GPU-precision triple. The relevant question is not the one-time cost but the recurring one: how often do you change model, quantisation or hardware? A team pinning one model for a year barely notices TensorRT-LLM's build. A team evaluating a new open-weight release every few weeks pays it every time, and that recurring cost usually swamps the throughput advantage it bought.
When to pick which
| Situation | Pick | Because |
|---|---|---|
| General agent fleet, mixed models, a team that has to operate it | vLLM | The ecosystem, the hardware breadth, and the largest supply of people who have debugged it. |
| High-concurrency agents on a stable prompt and toolset | SGLang | Automatic prefix sharing and constrained decoding that does not stall the batch — the two things agent traffic hammers. |
| One model, homogeneous NVIDIA fleet, latency is the product | TensorRT-LLM | Fastest absolute numbers, and the build cost amortises when nothing changes. |
| Local, edge, air-gapped, or shipped inside the app | llama.cpp | One binary, one file, no toolchain, runs on the hardware you already have. |
| You are not sure yet | vLLM, with prefix-aware routing on | Get the routing right first; the engine swap stays cheap and the routing win is larger anyway. |
FAQ
Is SGLang faster than vLLM?
On shared-prefix workloads, third-party H100 benchmarks in 2026 have put it roughly 15–30% ahead, and its architecture is the reason. But that gap is smaller than the one you create by load-balancing agent traffic round-robin, so fix routing before you migrate.
Why is llama.cpp the most-starred if it is the least deployed?
Stars measure people who ran something themselves, and llama.cpp is what most people use to run a model on a laptop. Datacentre serving is a much smaller population making a different choice.
Does TensorRT-LLM's compile step really take that long?
Tens of minutes per model, GPU architecture and precision combination is the number to plan against. It is a fixed cost, not a per-request one — the question is how often your configuration changes.
Can I run these on AMD or Apple hardware?
vLLM runs on ROCm, Intel XPU and TPU; SGLang reports AMD, Intel Xeon, TPU and NPU support; llama.cpp runs on nearly anything including Apple Silicon via Metal. TensorRT-LLM is NVIDIA-only by design.
What should I measure before choosing?
Prefix-cache hit rate on your real traffic, time-to-first-token split by cache hit and miss, and end-to-end task completion time rather than tokens per second. If those three are not instrumented, no benchmark comparison will predict your outcome.
Further reading
On this wiki:
- Self-Hosted Inference for Agents — the capacity arithmetic underneath this choice: KV-cache bytes, concurrent sequences, and why autoscaling does not work here.
- Prefill, Decode & the KV Cache — the two opposite bottlenecks inside one model call.
- Serving & Access: APIs, Local, Gateways — where self-hosting sits among the alternatives.
- Small & Local Models — which jobs never needed a frontier model in the first place.
- Prompt Caching — the same prefix-stability rule, on a hosted API.