
I have a confession: every time I reach for an OpenAI-compatible server to host a model locally, I feel a quiet annoyance. The chat completions API is a perfectly reasonable surface for chatbots. It is a terrible surface for agents, extractors, evaluators, and any code that fans a single prompt out into a graph of sub-calls. You end up hand-stitching JSON-mode flags, fighting grammars, and rebuilding prefix caching in your client.
SGLang — from the LMSys crew — is the project that finally said the quiet part out loud: the unit of work for an LLM application is a program, not a request. A runtime co-designed around that assumption makes a real difference, and after a few weeks of running it in production-adjacent workloads I am a convert for the use cases it targets.
SGLang ships two things in one repo:
1. A frontend language — Pythonic primitives (gen, select, fork, join) for composing LLM calls into branching and parallel programs. It looks like a tiny DSL but it is just Python with helper functions and decorators. 2. A high-performance serving runtime — an OpenAI-compatible HTTP server, a radix-tree-based prefix cache, continuous batching, paged KV memory, speculative decoding, and (newer) unified serving for diffusion models alongside LLMs.
The killer feature is RadixAttention: a global KV cache organized as a radix tree (a trie over token sequences) instead of per-request buckets. When two requests share a long common prefix — which is every agentic workload, every RAG pipeline, every eval harness that loops over a dataset — the shared prefix is computed once and reused. No client-side bookkeeping, no prompt deduplication gymnastics.
In practice that turns into a single-digit-percent waste on prefix tokens for workloads that previously re-prefilled the same system prompt thousands of times per minute. On a 70B-class model that is the difference between "we can run this on two H100s" and "we need four."
The 60-second tour. Drop a meta-llama/Llama-3.1-8B-Instruct (or any of the supported models) on a box with a recent NVIDIA GPU and you are off:
python -m pip install --upgrade pip python -m pip install "sglang[all]" # Single GPU serve (FP8 weights assumed for the 8B above; adjust to your model) python -m sglang.launch_server \ --model-path meta-llama/Llama-3.1-8B-Instruct \ --port 30000 \ --mem-fraction-static 0.85
Hit it with the OpenAI-compatible endpoint and it just works:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
model="meta-llama/Llama-3.1-8B-Instruct",
messages=[{"role": "user", "content": "Give me three SQL examples of window functions."}],
temperature=0.2,
)
print(resp.choices[0].message.content)The structured-generation side is where the DSL earns its keep. Imagine a router that classifies a question, then dispatches to a specialist — all in one server round trip:
import sglang as sgl
@sgl.function
def classify_and_answer(s, question: str):
# Branch 1: classify the question type
s += "Classify this question as 'math', 'code', or 'general'.\n"
s += f"Question: {question}\n"
s += "Category:"
s += sgl.gen("category", max_tokens=8, stop=[\"\n", "."])
# Conditional branches reusing the prefix cache
with s.user():
s += "You are a math tutor. Answer: " + question
s += sgl.gen("math_answer", max_tokens=256)
with s.user():
s += "You are a senior engineer. Answer: " + question
s += sgl.gen("code_answer", max_tokens=256)
# Fan-out select over the cached branches
s += "Given:\n"
s += "Math: {{math_answer}}\n"
s += "Code: {{code_answer}}\n"
s += "Return the better answer in JSON: {\"pick\": \"math\"|\"code\", \"reason\": str}"
s += sgl.gen("verdict", max_tokens=128, regex=r'\{[\s\S]*\}')
prog = classify_and_answer.run(
question="Why does my recursive CTE blow the stack on Postgres?",
backend=sgl.RuntimeEndpoint("http://localhost:30000"),
)
print(prog["verdict"])Three LLM calls, one shared prefix, one structured-JSON verdict at the end — and the runtime did the prefix reuse for you. If you have ever hand-written the orchestration for this in LangChain, you already know how much ceremony disappears.
Structured outputs are first-class: regex, JSON (with a Pydantic-shaped schema via sgl.function type hints), choice, and interval constraints. You can also point it at an xGrammar or Outlines backend. No more "the model returned markdown-wrapped JSON, now I have to regex-strip it."
vs. vLLM. vLLM is the throughput champion for chat-style traffic and the most polished OpenAI-compatible server in the ecosystem. SGLang uses the same underlying tensor-parallel kernels (and borrows a lot from vLLM), but its frontend and RadixAttention are built for program-shaped workloads. If your traffic is "lots of independent single-turn requests," vLLM is a fine pick. If your traffic is "agents, RAG, evals, tree search, anything that reuses a prefix," SGLang will quietly save you GPU-hours.
vs. TGI / TensorRT-LLM. Hugging Face TGI is the friendly default; TensorRT-LLM is the NVIDIA-tuned maximum-throughput play for production. Neither gives you a programmable frontend. They serve tokens; SGLang lets you compose tokens into a graph and amortizes the prefix.
vs. llama.cpp / Ollama. Wrong tool for the job. Those are single-user local runtimes; SGLang is a multi-tenant server. The overlap is "they all run LLMs," which is about as informative as saying a Postgres and SQLite overlap because they both store rows.
When not to use it. If your entire workload is a single user typing into a chatbox, the frontend DSL is dead weight and vLLM or TGI will be just as fast with less conceptual surface area. The first few versions also had rough edges on certain quantization formats — that gap has narrowed a lot through 2025 and into 2026, but check the supported models matrix before betting the farm on an exotic checkpoint.
SGLang is the most opinionated open-source LLM runtime I have shipped against in 2026. That is a compliment. It assumes you are building a real application — not a demo, not a chatbot — and the opinion pays for itself the moment you have a prefix worth caching.
Two things I genuinely like:
/v1/chat/completions. SGLang keeps that contract and layers the DSL on top. Adoption cost is close to zero for the boring path and enormous for the structured path.Two things I am still grumpy about:
sgl.gen with sgl.function. The docs help; the docs are not yet where vLLM's are.The short version: for inference, the conversation has moved on from "which model." The interesting question is "which runtime treats my workload as a first-class citizen." For structured, branching, prefix-heavy workloads, SGLang is the answer I reach for first.
Install it, point a real workload at it, watch the prefix-cache hit rate. If it does not change your GPU bill, I will eat this column.