Engine Compatibility
Check engine and transport compatibility before choosing images for a deployment. The requirements cover minimum releases, Mooncake client and store versions, supported transports and known failures.
Engines below the listed minimum versions are unsupported. Upgrade before diagnosing failures on an older engine release.
Contents
Minimum versions
The table covers aggregated serving, prefill/decode (PD) and encode/prefill/decode (EPD) configurations.
| Engine | Configuration | Minimum | Mooncake client | Store members |
|---|---|---|---|---|
| vLLM | alone | 0.29.0; behind llm-d-router, --enable-scale-out is also required on 0.30.0+ |
0.3.13.post1, on the cuda12.9 and the cuda13.0 tag |
— |
| vLLM | prefill/decode, direct transfer over tcp |
0.29.0; behind llm-d-router, --enable-scale-out is also required on 0.30.0+ |
0.3.13.post1 |
— |
| vLLM | with a Mooncake store, alone or as a pair | 0.29.0; behind llm-d-router, --enable-scale-out is also required on 0.30.0+ |
0.3.13.post1 |
the 0.3.13 line; the default image is one |
| vLLM-Ascend | alone | 0.23.0; behind llm-d-router, --enable-scale-out is also required on 0.30.0rc1+ |
0.3.11.post1, the NPU build |
— |
| vLLM-Ascend | prefill/decode, direct transfer | 0.23.0, behind llm-d-router; --enable-scale-out is also required on 0.30.0rc1+ |
0.3.11.post1, the NPU build |
— |
| vLLM-Ascend | with a Mooncake store | not verified | 0.3.11.post1, the NPU build |
not verified |
| SGLang | alone | 0.5.18, run as the halves of a pair |
0.3.12.post1 |
— |
| SGLang | prefill/decode, direct transfer over tcp |
0.5.18 |
0.3.12.post1 |
— |
| SGLang | with a Mooncake store | 0.5.18, run as a pair |
0.3.12.post1 |
the 0.3.12 line, such as kvcacheai/mooncake:0.3.12.post1 |
| vLLM | encode/prefill/decode, direct transfer over NIXL (ECCPUConnector) |
0.30.0, behind llm-d-router or vllm-router: NVIDIA CUDA (verified on 4 × NVIDIA L40S) or AMD ROCm (unverified on hardware) |
compiles its own, not run | — |
| vLLM-Ascend | encode/prefill/decode, direct transfer (ECExampleConnector) |
0.30.0rc1, behind llm-d-router (verified on Ascend 910B2) |
0.3.11.post1, the NPU build |
— |
| SGLang | encode/prefill/decode, transfer by address (encoder-urls) |
0.5.10, behind llm-d-router or sglang-gateway (NVIDIA verified on 2 × NVIDIA L40S) |
0.3.12.post1 |
— |
A version counts as run when the configuration answered requests and, where it moves KV, the engine or the
store reported blocks moving: a transfer or a store write, not a Pod reaching Ready. The
vLLM-Ascend rows ran on the runner’s cann9.1-910b-vllm0.23.0 tag, named through
roles[].image.
The NVIDIA vLLM EPD rows (behind llm-d-router and vllm-router) and the NVIDIA SGLang EPD rows
(run on 0.5.18, behind both routers) ran live. The vLLM-Ascend EPD row behind llm-d-router ran live on Ascend 910B2. The AMD EPD rows and the
SGLang Ascend rows are admitted but not verified on hardware
(#763
tracks them).
Reading the table
The minimum is a property of the image you name. There is no engine.version field to set:
the image a role runs resolves to roles[].image when the role names one, and to
spec.engine.image otherwise (Role images
).
Nothing assembles a tag and no admission check reads a version, so meeting a minimum here means
naming an image whose engine build carries it.
A deployment without an Encode role needs --enable-scale-out behind llm-d-router.
The router counts prompt tokens through the engine’s render endpoint, which vLLM serves only
under that flag, from 0.30.0 on; the gate measured on vllm-ascend is 0.30.0rc1. Name an
image at those versions and set the flag on each role
(Counting engine tokens
).
The 0.29.0 and 0.23.0 minimums above predate the flag: they were measured as transfer-path
runs, before the operator rendered this dependency.
The floor belongs to the engine, so an SGLang EPD
row states SGLang 0.5.10 on every platform, while the vLLM Ascend row states a vllm-ascend
release.
The client comes with the image. The column above is read off the
published runner images, and the vLLM rows are the CUDA ones; a ROCm runner image compiles its own
client and has not been run. A role naming its own roles[].image carries whatever client that
image embeds: read it off the image, then pick the store from it.
A store runs on the client’s minor line. The store column is a requirement rather than a suggestion; see Version compatibility .
vLLM-Ascend’s direct transfer does not support direct tcp transfer, and one router renders it; see Pair connections
.
The configurations above move KV over tcp, or over ascend on vLLM-Ascend. Which other transport
each engine can use is the matrix below
.
“Not verified” means no run, not a known failure. Nothing refuses such a configuration; nothing here says it works.
An EPD encoder image must meet its row’s floor, and nothing refuses a lower one. The
requirement: the image an Encode deployment runs must carry vllm-ascend 0.30.0rc1 or later for
Ascend ECExampleConnector, and vLLM 0.30.0 or later for NVIDIA/AMD ECCPUConnector
(the admitted matrix
). Admission does not check it — the version
field and its gate are gone.
An image below the floor fails at container start with an ImagePullBackOff on a tag that does not
exist, or an engine that exits on an unknown argument.
The group-forward probe has a verified version set, and nothing bars an unverified one. The
requirement: the version whose probe binding was read is 0.25.1/0.29.0 for vLLM (the response
id is cmpl- + the request’s request_id) and 0.5.18/0.5.21 for SGLang (the response
meta_info.id is the request’s rid).
On any other version the probe still runs and its outcome still decides: Verified admits a
member, Unknown grants nothing new and withdraws nothing already granted. Only a failed health
check of the same qualification
withdraws an eligible member. Neither probe outcome is an
admission refusal.
Transport compatibility
A store cell is the pool’s KVCacheBackend.spec.transport.protocol, which a member group can
override and the engine is handed. A direct cell is spec.kvTransfer.protocol on a
prefill/decode pair. The first column gives the API and Mooncake spellings. Auto renders
tcp on either path; the direct path also renders tcp when the field is unset.
| Transport (API / Mooncake) | Engine | Store path | Direct path |
|---|---|---|---|
Auto, TCP / tcp |
vLLM | Works, default images; beside a direct path it keeps its store connections open too and did not run out of ports where measured | Works, default images; it keeps its connections open and did not run out of ports where measured |
TCP / tcp |
SGLang | Works, with a published store image on its client’s line
, named by hand; beside a direct path, it runs out of ports
unless model-deployment-tcp-tw-reuse
is on |
Works, default images; under sustained load it runs out of ports
, and model-deployment-tcp-tw-reuse
is the remedy, run so far only beside a store |
TCP / tcp |
vLLM-Ascend | Not supported: refused at admission, its store client accepts CANN only |
Not supported: the value is ignored, the path runs ascend |
RDMA / rdma |
vLLM | Not verified | Works, default images on InfiniBand H100 SXM5 (Prefill and Decode Benchmark , Encode, Prefill and Decode Benchmark ) |
RDMA / rdma |
SGLang | Not verified | Not supported: the operator grants SGLang’s direct path no device |
RDMA / rdma |
vLLM-Ascend | Not supported: refused at admission, as for TCP |
Not supported: ignored, as for tcp |
EFA / efa |
vLLM | Own image: an EFA build of Mooncake in the engine; default store image | Own image: the same build on both ends |
EFA / efa |
SGLang | Not supported: no EFA build serves SGLang | Not supported: the operator grants SGLang’s direct path no device |
EFA / efa |
vLLM-Ascend | Not supported: refused at admission, as for TCP |
Not supported: ignored, as for tcp |
CANN / ascend |
vLLM | Not supported: the CUDA client has no Ascend transport | Not supported: the CUDA client has no Ascend transport |
CANN / ascend |
SGLang | Not verified | Not verified |
CANN / ascend |
vLLM-Ascend | Not verified; the members need an image carrying CANN | Works, cann9.1-910b-vllm0.23.0 named by hand in roles[].image, behind llm-d-router |
ROCM / hip |
vLLM, SGLang | Not verified | Not verified |
ROCM / hip |
vLLM-Ascend | Not supported: refused at admission, as for TCP |
Not supported: ignored, as for tcp |
MUSA, MACA / musa, maca |
vLLM, SGLang, vLLM-Ascend | Not verified | Rejected by the direct-path schema: these are same-node IPC transports, while prefill and decode have no same-node placement guarantee |
The vLLM and SGLang verdicts are read on their CUDA runner images. What each verdict means:
- Works: run on this operator with blocks moving, by the criterion under the minimum , on the images the cell names.
- Own image: works only on an engine image you build and keep up to date yourself.
- Not supported: admission refuses it, the operator renders nothing for it, or no image the cell could run carries the transport; the cell says which.
- Not verified: no run. Nothing refuses it; nothing here says it works.
“Default images” needs no image work from you: a stock runner image the project publishes,
named in engine.image or roles[].image, and the
kv-cache-backend-image
default for the store members. “Named by
hand” is a published image you write into roles[].image or the backend’s spec.image.
A cell is one path. A deployment using both paths is a separate configuration, read from the
minimum
rather than added up from two cells; both paths over EFA at once
have not been run. With a positive resources.interface, an RDMA path beside an EFA one is
refused at admission.
On AWS the RDMA rows do not apply; choose EFA or
TCP
.
Limitations
-
SGLang with a store holds a pinned host pool and needs the node’s available memory above a fixed reserve plus that pool; see SGLang’s host-memory tier .
-
SGLang prefill/decode over
TCPruns out of local ports under sustained load, with or without a store. The prefill half opens a new connection for every transfer, to the decode half and to each store member, all from the same ephemeral ports of its container. Connections left inTIME-WAITuse them up; from then on every request through that pair fails and keeps failing until the enginePods are restarted. On the measured pair without a store, the gateway then answered503withNo available prefill workers.Turning on
model-deployment-tcp-tw-reuseprevented failure in a measured SGLang 0.5.18 pair with a store: it answered 1905 sequential requests without failure, with about 19,500TIME-WAITsockets. It needs a kubelet change on every eligible node.The pair without a store was not tested with this setting. Widening
net.ipv4.ip_local_port_rangeonly delays exhaustion; whether a fabric transport avoids it remains unverified.vLLM did not show this behavior in the measured runs: its prefill half keeps its transfer connections open instead of opening one per transfer, and held at most nine sockets in
TIME-WAITover a direct path with no store and at most sixteen with aTCPstore beside it.