vLLM — A high-throughput and memory-efficient inference and serving engine for LLMs

code vllm-project-vllm
servinginferencepaged-attentioncontinuous-batchingkv-cachegpu-inference

vllm-project-vllm — L2 #

§1 TL;DR #

Dominant open-source LLM serving engine (81K stars). PagedAttention + continuous batching + CUDA graphs deliver SOTA throughput. V1 engine runs scheduler out-of-process via ZMQ; supports 200+ model architectures, disaggregated P/D, 10+ quantization formats, multi-vendor GPU.

§2 Project Identity #

FieldValue
Repo
Primary languagePython (36.3M LOC), CUDA (2.4M), Rust (1.9M), C++ (1.7M)
LicenseApache-2.0
Stars / Contributors81,023 / 2,000+
Version analyzedv0.21.0 (2026-05-15)
OriginUC Berkeley Sky Computing Lab (Woosuk Kwon, Ion Stoica, Hao Zhang)
GovernanceCommunity-driven, multi-corporate backing

§3 Motivation & Core Questions #

One-line pitch: Easy, fast, and cheap LLM serving for everyone.

Q1 痛点:KV cache fragmentation and batching inefficiency #

LLM inference wastes GPU memory and throughput due to two fundamental problems. First, static KV cache allocation wastes 60-80% of memory to internal fragmentation — each request pre-allocates the maximum possible KV cache regardless of actual usage, and freed memory cannot be reclaimed until the entire allocation is released. Second, without continuous batching, the system blocks on the longest-running request in a batch, leaving GPU cycles idle while shorter requests have already completed. These two problems compound: fragmented memory means fewer concurrent requests, and static batching means lower GPU utilization per request.

Q2 方法:PagedAttention + continuous batching + out-of-process scheduler #

PagedAttention manages KV cache as fixed-size blocks (like OS virtual memory pages), enabling dynamic allocation, deallocation, and copy-on-write sharing. A block table provides virtual→physical indirection, allowing blocks to be non-contiguous in GPU memory. Continuous batching allows new requests to enter and completed requests to leave mid-batch — the scheduler re-evaluates the request pool at every decode step. The V1 engine runs the scheduler in a dedicated process (connected via ZMQ IPC with msgspec serialization) to avoid GIL contention between the CPU-bound scheduler and GPU-bound model execution.

核心技术壁垒 #

PagedAttention's block-table indirection. The virtual→physical KV cache mapping enables COW prefix sharing, dynamic memory allocation, preemptive scheduling, and disaggregated serving (KV block transfer across nodes via NIXL). This single abstraction is what made continuous batching without memory waste practical. Every subsequent LLM serving system has adopted or reimplemented the idea — it is to LLM serving what virtual memory is to operating systems.

Q3 结果 #

Near-zero KV cache memory waste (<4% fragmentation vs 60%+ with static allocation), 2-4× throughput improvement over static-batch baselines, and de facto standard status for open-source LLM serving (81K GitHub stars, 200+ supported architectures, 2000+ contributors).

§4 Architecture & Module Map #

flowchart TB subgraph EP["Entrypoints (user-facing)"] LLM["LLM.generate()
Offline batch"] OAI["OpenAI API Server
FastAPI, SSE"] CLI["vllm serve / chat / bench
CLI"] GRPC["gRPC Server"] end subgraph V1["V1 Engine (dedicated process)"] EC["EngineCore"] SCHED["Scheduler
(priority queue + budget)"] BM["KV Cache Manager
(block pool, prefix cache)"] end subgraph EXEC["Execution Layer"] EX["Executor
(GPU / Ray / MultiProc)"] W["GPUWorker"] MR["GPUModelRunner
+ CUDA Graph Dispatcher"] end subgraph MODEL["Model Stack"] REG["ModelRegistry
(200+ architectures)"] ATT["Attention Backends
FlashAttn / FlashInfer / TRTLLM-GEN
FlashMLA / TOKENSPEED_MLA"] LIN["Linear / MoE Kernels
CUTLASS / CuTeDSL / Triton"] QNT["Quantization
FP8 / NVFP4 / MXFP4 / GPTQ / AWQ"] end subgraph MEM["Memory Subsystem"] KVC["KV Cache Pool
(GPU page blocks)"] PC["Prefix Cache (APC)"] OFF["KV Offload
(CPU / disagg via NIXL)"] end subgraph DIST["Distributed"] TP["Tensor Parallel
(NCCL allreduce)"] PP["Pipeline Parallel"] EP2["Expert Parallel
(elastic EP, EPLB)"] KVT["KV Transfer
(disagg P/D)"] end LLM -->|"ZMQ IPC (msgspec)"| EC OAI -->|"ZMQ IPC (msgspec)"| EC CLI --> OAI GRPC -->|"ZMQ IPC"| EC EC --> SCHED SCHED --> BM BM --> KVC KVC --> PC KVC --> OFF SCHED -->|"collective_rpc"| EX EX --> W W --> MR MR --> REG REG --> ATT REG --> LIN ATT --> QNT LIN --> QNT MR -->|"tokens + logprobs"| EC EC -->|"ZMQ IPC"| LLM EC -->|"SSE stream"| OAI W --> TP W --> PP W --> EP2 OFF --> KVT

Top modules by centrality:

ModulePurpose
vllm/entrypoints/User-facing: LLM (offline), OpenAI API server (online), gRPC, Anthropic API, MCP
vllm/v1/engine/EngineCore (scheduler + IPC), AsyncLLM, input/output processors
vllm/v1/core/Scheduler, KV cache manager, block pool, prefix caching
vllm/v1/worker/GPUWorker, GPUModelRunner, CUDA graph capture
vllm/v1/attention/Attention backend registry (FlashAttention, FlashInfer, TRTLLM-GEN, FlashMLA, TOKENSPEED_MLA)
vllm/model_executor/Model loading, weight management, 200+ architecture implementations
vllm/model_executor/layers/NN building blocks: attention, linear, MoE, quantization wrappers
vllm/distributed/TP / PP / EP / DP, allreduce, NCCL, KV transfer, EPLB
csrc/C++/CUDA/HIP kernels: paged attention, quantization, sampling, MoE, allreduce
vllm/platforms/Hardware abstraction: CUDA, ROCm, CPU, TPU, XPU, plugin system
vllm/v1/spec_decode/Speculative decoding: EAGLE, n-gram, MTP, DFlash
vllm/v1/structured_output/Constrained decoding: xgrammar, guidance, outlines, lm-format-enforcer
vllm/multimodal/Multi-modal input processing (images, video, audio)
vllm/config/VllmConfig dataclass hierarchy (100+ fields)
rust/Rust-based tokenizer for high-perf text processing

§5 Entry Points & API Surface #

Public API (import vllm) #

ExportRole
LLMOffline batch inference (.generate(), .chat(), .enqueue())
SamplingParamsGeneration parameter struct (temp, top_p, top_k, max_tokens, structured output)
RequestOutput / CompletionOutputOutput containers
EngineArgsEngine configuration from CLI args
AsyncLLMEngine / LLMEngineLegacy engine interfaces (V0, maintained for compat)
PoolingParamsEmbedding / classification / scoring params
ModelRegistryModel architecture registration

CLI Entry Points #

Top 10 Configuration Parameters #

FlagDefaultEffect
--model(required)HuggingFace model name or path
--tensor-parallel-size / -tp1Tensor parallelism degree
--pipeline-parallel-size / -pp1Pipeline parallelism degree
--gpu-memory-utilization0.92Fraction of GPU mem for KV cache
--dtypeautoWeight precision (float16/bfloat16/float32)
--quantizationNoneQuantization method (fp8, awq, gptq, …)
--max-model-lenautoMaximum sequence length
--enforce-eagerFalseDisable CUDA graphs + torch.compile
--enable-prefix-cachingFalseAutomatic prefix caching
--spec-method / --spec-modelNoneSpeculative decoding config

Extension Points #

§6 Core Data Structures #

SamplingParamsvllm/sampling_params.py #

VllmConfigvllm/config/ #

EngineCoreRequest / EngineCoreOutputvllm/v1/engine/__init__.py #

KV Cache Block Tables #

Requestvllm/v1/request.py #

§7 Critical Path Analysis #

Hot path: LLM.generate() → tokens out #

sequenceDiagram participant U as User participant LLM as LLM.generate() participant IPC as ZMQ IPC participant EC as EngineCore (OOP) participant S as Scheduler participant BM as BlockManager participant W as GPUWorker participant MR as ModelRunner participant GPU as GPU Kernels U->>LLM: prompts + SamplingParams LLM->>IPC: EngineCoreRequest (msgspec) IPC->>EC: deserialize loop until all requests done EC->>S: schedule() S->>BM: allocate KV blocks BM-->>S: block tables S->>W: collective_rpc(execute_model) W->>MR: build attention metadata MR->>GPU: model.forward() Note over GPU: embed → N×(attn+MLP) → LM head GPU->>MR: logits MR->>MR: sample(top_k/top_p/temp) MR-->>W: token_ids + logprobs W-->>EC: ModelRunnerOutput EC->>EC: update state, check stop end EC->>IPC: EngineCoreOutput (msgspec) IPC->>LLM: deserialize LLM->>LLM: detokenize LLM-->>U: list[RequestOutput]

Latency breakdown per decode step #

HopBottleneckDominant cost
IPC serialize/deserializeCPU, msgspec~0.1 ms (zero-copy)
Scheduler (schedule())CPU, single-thread Python~0.01–0.1 ms
Block managerCPU~0.01 ms
Model forward (decode)GPU, memory-bandwidth-bound~5–50 ms (model-size dependent)
Attention kernelGPU VRAM bandwidthmajor fraction of forward
SamplingGPU (FlashInfer sampler)~0.1 ms
DetokenizationCPU~0.01 ms

Prefill is compute-bound ($O(n^2)$ in sequence length for attention, $O(n)$ for FFN); decode is memory-bandwidth-bound (one token at a time reads full KV cache per layer).

README vs. reality #

README claims "state-of-the-art serving throughput." The architecture supports this via continuous batching + PagedAttention + CUDA graphs. The main tension point: the EngineCore monolith (core.py, ~89KB) is single-threaded Python — at extreme QPS (thousands of concurrent requests), scheduler CPU time could bottleneck before GPU saturates. The V1 engine mitigates this by running the scheduler in a dedicated process (eliminating GIL contention with model execution), but the single-threaded scheduler remains the theoretical ceiling.

§8 作者证明 #

无形式化作者证明 — 仅实证。

vLLM's claims are validated empirically through published benchmarks (the original SOSP'23 paper shows 2-4× throughput gains over baselines) and sustained community adoption (81K stars, adoption by major cloud providers). No formal correctness proofs exist for the scheduler, block manager, or attention kernel implementations. Memory safety relies on the block table invariant: every physical block is either free, uniquely assigned to one virtual block, or COW-shared with a positive reference count — but this invariant is enforced by runtime logic, not proven.

§9 Concurrency & Memory #

Concurrency Model #

MechanismWhereWhy
Multi-processEngineCore vs. workersGIL avoidance: scheduler (CPU-bound Python) and model execution (GPU-bound C++ extensions) run in separate processes
ZMQ IPCEngine ↔ worker boundaryLow-latency message passing with msgspec zero-copy serialization
CUDA streamsModel executionAsync GPU execution, overlap compute with memory transfers
CUDA/HIP graphsDecode phaseCaptured execution graphs eliminate kernel launch overhead
torch.compileModel forwardPiecewise compilation for kernel fusion and graph-level optimization
RayMulti-nodeOptional distributed executor for cross-node TP/PP
asyncioAPI serverAsync HTTP/SSE handling in FastAPI server process

GIL Avoidance Strategy #

The V1 engine's key architectural insight: the EngineCore process runs the scheduler (pure Python, CPU-bound) while GPUWorker processes run model execution (mostly C++/CUDA extensions that release the GIL). The ZMQ IPC boundary is the price paid for process isolation — ~0.1ms per step via msgspec, much cheaper than GIL contention would be. The IPC uses msgspec Struct serialization rather than pickle, reducing overhead by 10-100×.

Memory Management #

Concurrency Concerns #

  1. The scheduler is single-threaded — at very high QPS (thousands of concurrent requests), scheduler CPU time could bottleneck before GPU saturates.
  2. CUDA graph capture requires fixed tensor shapes. Dynamic batch sizes fall back to eager mode. The solution: capture graphs for multiple batch sizes and select at runtime via CUDAGraphDispatcher.
  3. Multi-node TP requires NCCL allreduce on every transformer layer — network bandwidth becomes the scaling limit at >8 GPUs.
  4. §10 Performance Characteristics #

    Key Performance Mechanisms #

    MechanismBenefitMagnitude
    PagedAttentionNear-zero KV cache fragmentation<4% waste vs 60%+ static
    Continuous batchingGPU never idles waiting for longest request2-4× throughput over static
    Chunked prefillLong prompts interleaved with decodeReduces TTFT variance
    Prefix caching (APC)Shared KV blocks for common prefixesUp to 2× throughput for shared-prefix workloads
    CUDA/HIP graphsEliminate kernel launch overhead15-30% decode speedup
    torch.compileAutomatic kernel fusionVariable, model-dependent
    Speculative decodingMultiple tokens per step2-3× decode speedup (EAGLE/MTP)
    Quantization (FP8/NVFP4/INT4)Reduced memory + faster GEMM2-4× memory, 1.5-2× throughput
    Disaggregated P/DSeparate prefill and decode poolsOptimizes for different compute profiles

    Scaling Behavior #

    • TP (tensor parallelism): near-linear throughput scaling up to 8 GPUs within a node; limited by allreduce overhead at higher degrees
    • PP (pipeline parallelism): enables models exceeding single-node memory; bubble overhead ~$\frac{p-1}{m+p-1}$ for $p$ stages, $m$ microbatches
    • EP (expert parallelism): for MoE models (DeepSeek-V3/V4, Mixtral); elastic EP with EPLB for dynamic expert load balancing
    • DP (data parallelism): via coordinator process; near-linear throughput scaling
    • Disaggregated P/D: separate prefill and decode GPU pools connected via NIXL for KV cache transfer

    v0.21.0 Performance Highlights #

    • FlashInfer top-k/top-p sampler as default
    • AllPool 51% faster
    • GPU-CPU sync elimination in hot path
    • NVFP4 all-gather GEMM fusion
    • Persistent MLA for DeepSeek models
    • TOKENSPEED_MLA on Blackwell GPUs for DeepSeek-R1/Kimi-K25
    • KV Offload + Hybrid Memory Allocator integration

    §11 论证链 #

    StepClaimEvidenceDepends on
    1Static KV cache allocation wastes 60-80% of GPU memory to internal fragmentationSOSP'23 paper §2: measured fragmentation on Llama-13B/OPT-30B workloads
    2Virtual memory–style paging (PagedAttention) reduces fragmentation to <4%Block table indirection allows non-contiguous allocation; waste is at most block_size−1 tokens per sequenceStep 1
    3Near-zero fragmentation → more concurrent requests → higher GPU utilizationMore KV cache capacity means more sequences fit in memory simultaneouslyStep 2
    4Continuous batching exploits the freed capacity — new requests enter mid-batch as others completeScheduler re-evaluates every decode step; no idle GPU cycles waiting for batch stragglersSteps 2, 3
    5COW block sharing enables prefix caching and parallel sampling without memory duplicationBlock table indirection makes COW a pointer update, not a data copy; APC shares common system promptsStep 2
    6Out-of-process scheduler eliminates GIL contention between CPU scheduling and GPU executionV1 engine: EngineCore in separate process via ZMQ IPC; msgspec serialization costs ~0.1ms vs GIL contention measured at ms-scaleSteps 3, 4
    7Combined system achieves 2-4× throughput over static-batch baselines and becomes the de facto open-source serving standard81K GitHub stars, 200+ models, 2000+ contributors; adopted by major cloud providers; biweekly releases with 200+ contributors per releaseSteps 1-6

    §12 Tech Debt & Code Quality #

    Known Debts #

    IssueSeverityStatus
    core.py at ~89KBHigh (maintainability)Architectural — deliberate perf-over-readability trade-off
    Dual engine (V0 engine/ + V1 v1/engine/)MediumV0 maintained for compat only, V1 is default
    200+ individual model filesMedium (maintenance)Each arch has its own impl; boilerplate accumulates
    C++20 build requirement (v0.21.0)LowDriven by PyTorch upstream; breaks older GCC <10
    Transformers v4 deprecationLowMigration to v5 in progress
    DeepSeek V4 separate sub-packageLowvllm/models/deepseek_v4/ lives outside normal model registry

    Build System #

    • scikit-build + CMake for native extensions (CUDA/HIP/CPU)
    • Per-platform requirements files in requirements/
    • Docker builds for CUDA, ROCm, CPU variants
    • Rust build via build_rust.sh for tokenizer

    CI & Testing #

    • Buildkite: primary CI pipeline (.buildkite/)
    • GitHub Actions: auxiliary checks (.github/)
    • Test suite: comprehensive — unit, integration, distributed tests in tests/
    • Benchmarks: dedicated scripts in benchmarks/ for offline and online throughput/latency

    Linting #

    • ruff for Python linting and formatting
    • Type checking infrastructure present
    • clang-format for C++/CUDA code

    Dependency Health #

    DependencyHealthRisk
    PyTorchActively maintained, tracked closelyC++20 requirement cascade
    HuggingFace Transformersv5 migration underwayBreaking API changes
    FlashAttention / FlashInferActively maintainedFlashAttention: NVIDIA-only
    msgspecSmall but maintainedLow bus factor, critical on IPC path
    xgrammar / guidance / outlinesVarying maturityFragmented structured output ecosystem
    NCCLNVIDIA-maintainedAMD equivalent (RCCL) tracked separately

    §13 Community Health #

    MetricValue
    Commits per minor release367 (v0.21.0)
    New contributors per release49 (v0.21.0)
    Total contributors2,000+
    GitHub stars81,023
    Release cadence~biweekly minor releases with patch releases between
    OriginUC Berkeley Sky Computing Lab (Kwon, Stoica, Zhang)
    GovernanceCommunity-driven, multi-corporate participation
    CommunicationGitHub Issues, vLLM Forum (discuss.vllm.ai), Developer Slack (slack.vllm.ai)
    Bus factorHigh — 202 contributors in a single release, core team spans multiple organizations
    AI agent integrationAGENTS.md and CLAUDE.md at repo root for AI-assisted development

    §14 Comparison with Alternatives #

    DimensionvLLMTensorRT-LLMSGLangTGI (HuggingFace)
    LanguagePython + C++/CUDAC++ + PythonPython + C++Rust + Python
    Model support200+ archs~30~50~60
    HardwareNVIDIA, AMD, CPU, TPU, 7+ pluginsNVIDIA onlyNVIDIA, AMDNVIDIA, AMD
    Memory mgmtPagedAttentionPaged KV cacheRadixAttentionPagedAttention
    Peak perf (NVIDIA)Very highHighestVery highHigh
    QuantizationFP8/NVFP4/MXFP4/INT8/INT4/GPTQ/AWQ/GGUFFP8/INT8/INT4FP8/INT8/AWQGPTQ/AWQ/BNB
    Structured output4 backendsLimited1 backend1 backend
    Disaggregated P/DYes (NIXL)YesYesNo
    Spec decodeEAGLE/n-gram/MTP/DFlashDraft modelEAGLENo
    API compatOpenAI + Anthropic + gRPC + MCPTriton Inference ServerOpenAIOpenAI
    Ease of installpip install vllmDocker + TensorRTpip installDocker
    LicenseApache-2.0Apache-2.0Apache-2.0Apache-2.0
    Community81K stars, 2K+ contrib~16K stars~25K stars~10K stars

    Winner by scenario:

    • Maximum NVIDIA performance, controlled model set → TensorRT-LLM
    • Broadest model/hardware support, production serving → vLLM
    • LLM programming, multi-call chains, RadixAttention → SGLang
    • HuggingFace ecosystem, minimal config → TGI

    §15 实现 Cross-Reference #

    Key file:line citations #

    ComponentFileRole
    Offline entrypointvllm/entrypoints/llm.pyLLM.__init__ — builds EngineArgs → VllmConfig → LLMEngine
    V1 LLMEnginevllm/v1/engine/llm_engine.pyLLMEngine.__init__ — creates InputProcessor, OutputProcessor, EngineCore client
    EngineCorevllm/v1/engine/core.pyMonolithic scheduler loop — schedule, dispatch, collect outputs (~89KB)
    V1 Schedulervllm/v1/core/sched/scheduler.pyScheduler.schedule() — request admission, token budget, block allocation
    KV Cache Managervllm/v1/core/Block pool management, prefix caching, COW logic
    GPU Model Runnervllm/v1/worker/gpu_model_runner.pyexecute_model() — builds inputs, runs forward, samples, returns tokens
    CUDA Graph Dispatchervllm/v1/cudagraph_dispatcher.pySelects pre-captured graph by batch size
    OpenAI API Servervllm/entrypoints/openai/api_server.pyFastAPI app, build_async_engine_client(), routes for /v1/completions, /v1/chat/completions
    Paged Attention Kernelscsrc/attention/C++/CUDA paged attention v1/v2/MLA kernels
    Quantization Kernelscsrc/quantization/FP8, INT8, INT4, GPTQ, AWQ CUDA kernels
    MoE Kernelscsrc/moe/Fused MoE, topk selection
    Sampling Kernelcsrc/sampler.cuGPU-side sampling
    KV Transfervllm/distributed/kv_transfer/Disaggregated P/D connectors (NIXL, etc.)
    Platform Abstractionvllm/platforms/CUDA, ROCm, CPU, TPU, XPU dispatch
    Model Registryvllm/model_executor/models/200+ model architecture implementations
    Config Hierarchyvllm/config/VllmConfig and all sub-configs

    関鍵実装細節 #

    1. msgspec for IPC serialization: SamplingParams and EngineCoreRequest/Output use msgspec.Struct instead of dataclasses. This enables zero-copy serialization across the ZMQ IPC boundary, avoiding the 10-100× overhead of pickle. The choice of omit_defaults=True further reduces wire size for the common case where most sampling parameters are left at defaults. This design decision is load-bearing — switching to pickle would measurably increase per-step latency and could make the IPC boundary the bottleneck at high QPS.
      1. Monolithic scheduler for hot-path locality: vllm/v1/engine/core.py packs the entire scheduling loop into one ~89KB file to minimize cross-module function call overhead on the hot path. Python function calls across modules involve dict lookups and frame creation that are measurable at thousands of scheduling decisions per second. This is a deliberate performance-over-readability trade-off that trades maintainability for ~microseconds per step.
        1. Multi-size CUDA graph capture: the CUDAGraphDispatcher pre-captures CUDA execution graphs for multiple batch sizes at startup (during capture_model()). At runtime it selects the smallest graph that fits the current batch, avoiding the 15-30% decode overhead of eager execution. The batch-size set is determined by profiling during profile_run(), which measures maximum KV cache capacity.
        2. §16 Verdict & Recommendations #

          When to adopt ("yes" regime) #

          • You need to serve any HuggingFace model with an OpenAI-compatible API in production
          • You need multi-hardware support (NVIDIA + AMD + CPU + custom accelerators via plugins)
          • You want the largest community, fastest bug fixes, and broadest model support (200+)
          • You need advanced features: LoRA serving, structured output (4 backends), multimodal, speculative decoding, disaggregated P/D
          • You need a single serving stack across diverse model architectures

          When NOT to adopt ("no" regime) #

          • You need absolute peak NVIDIA performance and can tolerate complex deployment → TensorRT-LLM
          • Your workload is multi-step LLM programming with prefix-heavy patterns → SGLang's RadixAttention and frontend DSL provide structural advantages
          • You need a minimal, embedded serving library → vLLM's dependency footprint is substantial (PyTorch + CUDA + numerous Python deps)
          • You're running models <1B parameters where batching overhead exceeds compute benefit
          • You cannot build C++20 extensions in your environment (v0.21.0+)

          Suggested contributions if contributing #

          1. Split core.py: the ~89KB monolith is the project's biggest maintainability risk. Extracting the scheduler, request state machine, and IPC handling into separate modules would improve testability without meaningful perf regression (the IPC boundary already forces serialization).
          2. Unify attention backend selection: the 6+ attention backends have ad-hoc selection logic. A benchmark-driven auto-selector (profile each backend during startup, cache results) would reduce user confusion and ensure optimal kernel choice per model architecture.
          3. Standardize model implementations: the 200+ model files share substantial boilerplate. A generic adapter layer (even if opt-in) for common patterns (standard transformer, standard MoE) would reduce the maintenance burden for long-tail models while preserving per-model optimization for critical architectures.
          4. Common Gotchas #

            1. gpu_memory_utilization=0.92 is aggressive — will OOM on GPUs shared with other processes. Lower to 0.80–0.85 in shared environments.
            2. enforce_eager=True kills performance — disables CUDA graphs and torch.compile. Only use for debugging.
            3. max_model_len auto-detection — reads from model config, which can be 128K+ for long-context models. Will OOM on memory-constrained GPUs. Set explicitly.
            4. Prefix caching is not default--enable-prefix-caching must be set explicitly. For workloads with shared system prompts this can double throughput.
            5. V1 engine IPC overhead — the out-of-process EngineCore adds ~1ms latency per step via ZMQ, but eliminates GIL contention. Net positive for online serving, slight overhead for single-batch offline.
            6. Not all models support all features — TP/PP, quantization compatibility, and multi-modal support vary per architecture. Check docs before assuming.
            7. C++20 build requirement (v0.21.0+) — needs GCC ≥10 or Clang ≥10. Will break older build environments silently.