The runtime landscape: which engine when?
llama.cpp, Ollama, LM Studio, vLLM, MLX, SGLang and friends compared: what each is built for, how they differ on hardware, formats and concurrency, a decision tree, and how to migrate between them without rewriting your app.
There is no single best way to run a model locally. Different runtimes are built for different jobs: tinkering on a laptop, squeezing a model onto odd hardware, serving a hundred users, or shipping one executable. Choosing well saves weeks, and choosing badly (for example vLLM for a single-user laptop, or Ollama for a 100-user API) is a classic and avoidable mistake.
| Runtime | Best for | Hardware | Format | Concurrency |
|---|---|---|---|---|
| llama.cpp | Max control, any hardware | CPU, CUDA, Metal, Vulkan, ROCm, SYCL | GGUF | Good (slots) |
| Ollama | Easiest start, local dev | Same as llama.cpp | GGUF | Basic |
| LM Studio / Jan | GUI users | Same | GGUF (+MLX in LM Studio) | Basic |
| vLLM | Production serving | NVIDIA (also AMD, TPU, CPU) | HF/AWQ/GPTQ/FP8 | Excellent |
| MLX / mlx-lm | Apple Silicon speed | Mac | MLX | Limited |
| llamafile | One-file distribution | CPU/GPU | GGUF | Basic |
| SGLang / TGI | Production serving alternatives | NVIDIA | HF | Excellent |
Simplified map. โBuilt inโ means you do not need extra software for that layer. Tools overlap and change quickly, so check current docs.
#The layers underneath
Most tools you will meet are layers on a few engines:
- ggml / llama.cpp is the C/C++ inference engine behind Ollama, LM Studio, llamafile, Jan and many apps. It is portable, quantisation-first and runs on almost anything.
- PyTorch-based servers (vLLM, SGLang, TGI) run models in 16-bit or compressed GPU formats with batching built for throughput.
- MLX is Apple's own array framework for Apple Silicon.
- Vendor stacks (TensorRT-LLM and others) squeeze maximum speed from specific GPUs, at the cost of build complexity.
Knowing the layer tells you what to expect: a front-end built on llama.cpp inherits its model support and its quirks, and its updates.
#Each runtime in a paragraph
llama.cpp. The Swiss army knife. Builds for every major backend, supports partial offload (some layers on GPU, rest on CPU), the widest set of quant types, grammar and JSON-schema constrained output, speculative decoding, embeddings and a built-in web UI. You assemble flags yourself, which is both its power and its learning curve (llama.cpp lesson).
Ollama. A daemon plus CLI plus model registry around llama.cpp. ollama run <model> downloads and chats. Modelfiles customise prompts and parameters. It provides a native API and an OpenAI-compatible one. Defaults are conservative (notably a small context window), and concurrency is basic (Ollama lesson).
LM Studio and Jan. Desktop apps with model browsers, chat UIs and a local server. Ideal if you prefer clicking to typing. LM Studio can also run MLX models on Macs.
vLLM. A Python server for GPUs focused on throughput: continuous batching and PagedAttention let one GPU serve many streams efficiently. It prefers Hugging Face weights and GPU-oriented quantisations (AWQ, GPTQ, FP8). Heavier to install, GPU-first, excellent for teams and products (vLLM lesson).
MLX and mlx-lm. Apple's framework designed around unified memory. Often fast on newer chips, with built-in quantisation and LoRA fine-tuning. Mac only (MLX lesson).
llamafile. Packs a model and llama.cpp into a single executable that runs on several operating systems. Great for distribution to non-technical users.
SGLang and TGI. Other production-grade GPU servers. SGLang is known for its structured-generation and prefix-caching features; Hugging Face's TGI integrates tightly with the Hub. Evaluate them against vLLM for your workload.
#Decision tree
- Just trying models on my laptop โ Ollama or LM Studio.
- Want full control, odd hardware, partial CPU/GPU offload, grammars โ llama.cpp.
- On a Mac and want best speed or want to fine-tune โ MLX (or llama.cpp with Metal; benchmark both).
- Serving a team or product on NVIDIA GPUs โ vLLM (or SGLang/TGI after testing).
- Shipping a single executable to users โ llamafile or embed llama.cpp.
- Running in a browser or on a phone โ see edge options.
- Need maximum throughput on a fixed NVIDIA fleet โ consider vendor stacks, after you have measured that the simpler engines are not enough.
#Questions to ask
| Question | Pushes you toward |
|---|---|
| How many users at once? | 1 to 3: Ollama or llama.cpp. 10 or more: vLLM |
| What hardware? | Mac: MLX or llama.cpp. NVIDIA: any, vLLM for serving. AMD, Intel or Vulkan-only: llama.cpp |
| Does the model fit in memory? | If not, llama.cpp partial offload or a smaller quant |
| Which model format is available? | GGUF: llama.cpp family. HF safetensors with AWQ or FP8: vLLM |
| Need structured output or grammars? | llama.cpp, vLLM and SGLang all support it, with different syntax |
| Operational maturity? | Production needs health checks, metrics and batching: vLLM or llama-server behind a gateway |
| Who will run it? | Non-technical users: LM Studio, llamafile |
#The same model, different engines
Most engines expose an OpenAI-compatible API, so your application code does not need to change when you swap runtimes (serving):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="x") # Ollama
# base_url="http://localhost:8080/v1" # llama-server
# base_url="http://localhost:8000/v1" # vLLMThings that do differ between engines: model names, which sampling parameters are accepted (min-p, repeat penalty and similar are often runtime-specific), tool-calling parsers, structured-output syntax and error messages. Keep these behind a small adapter so you can switch without touching business logic.
#Comparing runtimes fairly
Benchmarks of runtimes are only meaningful if you hold things constant:
- The same model and equivalent precision. GGUF Q4_K_M and AWQ 4-bit are not identical in size, speed or quality.
- The same context length and concurrency.
- The same prompts, including prompt length (prefill-heavy versus decode-heavy workloads favour different engines).
- Warm-up first, then measure several runs.
- Report both prompt processing and generation speed, and for servers, throughput under load with latency percentiles (load testing).
A single tokens-per-second number from a blog post, measured on someone else's hardware, rarely transfers. Measure yours (benchmark lab).
#Migrating between runtimes
| From โ to | What to watch |
|---|---|
| Ollama โ llama.cpp | Export or locate the GGUF, replicate parameters (num_ctx โ -c), set the chat template (--jinja), add -ngl |
| llama.cpp โ vLLM | Different model format (HF weights or AWQ/GPTQ/FP8); different memory model (--gpu-memory-utilization, --max-model-len) |
| Anything โ MLX | Convert or download an MLX version; different quant types |
| Dev laptop โ production | Add authentication, TLS, metrics, health checks, limits (production endpoint lab) |
#Common mistakes
- Using vLLM for a single-user laptop (heavy, GPU-only) or Ollama for a 100-user API (not designed for it).
- Comparing runtimes with different quantizations or context sizes.
- Ignoring defaults: Ollama's default context is small, so set it explicitly.
- Choosing by benchmark headlines rather than by your workload.
- Exposing a runtime with no authentication to a network (stack security).
- Running with out-of-date versions: runtimes evolve quickly, and new model architectures need new releases.
#Exercise
For each, pick a runtime and justify it in one sentence:
- A designer wants to try ten models on a MacBook Air with no terminal use.
- A startup serves a support bot to 200 concurrent users on two A100 GPUs.
- A hobbyist has an old laptop with 16 GB of RAM and a small integrated GPU.
- A researcher on a 128 GB Mac Studio wants to fine-tune a 7B model with LoRA.
Answers: (1) LM Studio, since a GUI with a model browser needs no setup. (2) vLLM behind a gateway, for continuous batching and high concurrency. (3) llama.cpp or Ollama with a small quantised model on CPU, where portability and low overhead matter. (4) MLX (mlx-lm), which has built-in LoRA and uses the unified memory efficiently.
Quick quiz
+10 XP per correct answer, +25 XP for a perfect score
1. Which is best suited to serving many concurrent users on NVIDIA GPUs?
2. Ollama is built on top of...
3. Your application talks to an OpenAI-compatible endpoint. What happens when you swap the runtime behind it?
4. Which setup suits a single user on a laptop who wants to try many models quickly?
5. Comparing llama.cpp and vLLM throughput with different quantizations and context sizes is...