← Back to Payloads
Open Source2026-07-08

SGLang is the Open-Source Inference Runtime That Finally Treats Structured Output as a First-Class Citizen

Most LLM serving stacks bolt structured generation on top of a chat-completion engine. SGLang flips the script — a frontend DSL and runtime co-designed for branching, parallel, and constrained LLM programs. If your workload looks like an agent, a tree-of-thought, or a JSON-schema-heavy pipeline, it deserves a serious look.
Quick Access
Install command
$ mrt install open source
Browse related skills
SGLang is the Open-Source Inference Runtime That Finally Treats Structured Output as a First-Class Citizen

SGLang is the Open-Source Inference Runtime That Finally Treats Structured Output as a First-Class Citizen

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.

What it actually does

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."

How it works in code

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:

bash
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:

python
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:

python
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."

Where it fits vs. the alternatives

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.

My take

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:

  • The OpenAI surface stays. Every team I work with already has client code targeting /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.
  • Diffusion + LLM unified serving. The 2026 releases added unified serving for diffusion models alongside LLMs in a single deployment. It sounds like a footnote; it is actually a sign the team thinks about serving as a systems problem rather than a per-model problem.

Two things I am still grumpy about:

  • The Python DSL has a small learning curve and the error messages are still a little too close to the metal. Newcomers regularly confuse sgl.gen with sgl.function. The docs help; the docs are not yet where vLLM's are.
  • Hardware support skews NVIDIA. AMD and other accelerators are catching up, but if your fleet is ROCm-only, double-check before committing.

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.

Related Dispatches