Serving Configuration¶
Overview¶
This document describes the canonical configuration of the serving arguments and the rationale for each value. It does not stop at listing values. It also explains why each value was chosen and what changes when the value is changed.
Status badges on this page follow Reference Design › Status badges: a statement without a badge is not Validated.
The principle that runs through the entire configuration is latency-first: per-request latency takes priority over the batch size that would raise aggregate throughput.
Argument names follow the vllm serve CLI. For the engine-argument form of these names and for the RBLN-specific constraints that apply to them, see the Configuration Guide.
Canonical configuration¶
The model is MiniMaxAI/MiniMax-M2.7.
Common arguments¶
The Status column records whether each value was exercised in the validation of the Target Configuration.
| Argument | Value | Status |
|---|---|---|
--block-size | 4096 | Validated (see --block-size 4096) |
--max-model-len | 204800 | Validated |
--max-num-batched-tokens | 512 | Validated |
--kv-cache-dtype | fp8 | Validated |
VLLM_RBLN_SUB_BLOCK_CACHE | 1 | Validated |
--enable-prefix-caching | Used | Validated |
--enable-chunked-prefill | Used | Validated |
--tool-call-parser | minimax_m2 | Validated |
--reasoning-parser | minimax_m2 | Validated |
--enable-auto-tool-choice | Used | Validated |
The three tool-call and reasoning arguments were exercised by the agent workload in Validation and Limits, in which mini-swe-agent makes tool calls over many turns.
Role-specific arguments¶
| Argument | Prefill | Decode | Status |
|---|---|---|---|
| Parallelism | PP4 (DP1, TP1) | DP4 (PP1, TP1) | Validated |
| Expert parallel | Disabled | Enabled | Validated |
--max-num-seqs | 4 | 1 | Validated (decode was also run at 2, 4, and 8 above concurrency 16) |
--gpu-memory-utilization | 0.8 | Not set (engine default) | Validated |
| KV connector | LMCache (RDS) + NIXL | NIXL only | Default configuration for LMCache (feature and accuracy validation; the Target Configuration validation used NIXL only on both roles) |
| Speculative decoding | Used (EAGLE-3) | Used (EAGLE-3) | See Speculative decoding |
LMCache environment variables (prefill only)¶
Default configuration: the feature and accuracy validation confirmed the behavior; the effect was not measured. These are configured through environment variables only, without a configuration file; the chart's default values carry them in modelserver.extraServeEnv.prefill.
| Environment variable | Value |
|---|---|
LMCACHE_CHUNK_SIZE | 4096 (the default equals --block-size; any value that divides --block-size works) |
LMCACHE_LOCAL_CPU | false |
LMCACHE_MAX_LOCAL_CPU_SIZE | 0 |
LMCACHE_ENABLE_KV_EVENTS | true |
LMCACHE_PRE_CACHING_HASH_ALGORITHM | sha256_cbor_64bit |
LMCACHE_STORAGE_PLUGINS | RDSBackend |
LMCACHE_EXTRA_CONFIG | RDSBackend module path and class name; rds_max_chunks goes here |
The RDS capacity is a number of chunks per rank, not a disk size: each rank (engine process) keeps at most rds_max_chunks chunks (default 1000, set by adding rds_max_chunks to LMCACHE_EXTRA_CONFIG) on the device bound to RDS, and evicts the least recently used chunk before storing a new one. At the default and LMCACHE_CHUNK_SIZE 4096, each rank holds up to 4,096,000 tokens (rds_max_chunks × LMCACHE_CHUNK_SIZE) in RDS. Each stored chunk holds 2 MiB of chiplet 0 memory per NVMe drive, so rds_max_chunks × 2 MiB × the number of drives, plus the staging buffer, has to fit in the chiplet 0 memory that --gpu-memory-utilization leaves. Change the two values together. lmcache-rbln older than 0.12.0 does not read rds_max_chunks. The device requirement is in Node preparation › RDS setup.
Speculative decoding (both roles)¶
The same value goes on both roles: EAGLE-3 needs --speculative-config on prefill too, because the draft head fills its own KV cache during the prefill forward pass.
Router (llm-d EPP/GAIE)¶
The canonical configuration uses prefix-cache-aware routing, with the plugins below. The scorer weights follow the upstream pd-epp-config, which is what the serving chart deploys. Unverified as a whole. Routing chooses among several Pods, so the feature and accuracy validation, with one prefill and one decode, cannot confirm it; the Target Configuration validation did not use this configuration.
The P/D deployments of the feature and accuracy validation used the same plugins and weights as this table.
| Plugin / setting | Value |
|---|---|
prefix-based-pd-decider | nonCachedTokens: 1: when the router's estimate of uncached tokens is below 1, the request skips prefill and goes straight to decode. 0 sends every request straight to decode without prefill |
disagg-profile-handler | Used |
prefill-filter, decode-filter | Used |
approx-prefix-cache-producer | maxPrefixTokensToMatch: 204800; blockSizeTokens and lruCapacityPerServer are derived per Pod by autoTune (see KV capacity referenced by the router) |
prefix-cache-scorer | weight 2.0 |
queue-scorer | weight 1.0 |
max-score-picker | Used |
kv-cache-utilization-scorer, precise-prefix-cache-scorer | Not used |
The router records which Pod it sent a request to; it does not ask whether the engine actually cached it. A repeated prompt therefore skips prefill. For a measurement in which every request must pass through prefill, use always-disagg-pd-decider instead of prefix-based-pd-decider.
The AGG recipes have no prefill Pods and use different plugins: approx-prefix-cache-producer, inflight-load-producer, prefix-cache-affinity-filter, and token-load-scorer in a single scheduling profile. The peakPrefillThroughput of prefix-cache-affinity-filter is 2256 (tokens per second), measured on this model's AGG configuration.
Parallelism¶
PP and DP exclusivity¶
The entrypoint rejects the combination of pipeline-parallel-size > 1 and data-parallel-size > 1. This constraint effectively determines the per-role configuration: prefill becomes PP4/DP1 and decode becomes DP4/PP1.
Prefill: PP4¶
PP4 splits the 62 layers four ways, so the weights are distributed over four cards and each stage exchanges only activations at layer boundaries.
Decode: DP4, expert parallel enabled¶
Decode generates one token at a time per request, so only a small number of experts activate. DP4 is combined with expert parallel to distribute the 256 experts over four cards. Decode cannot use PP, so without expert parallel every card would need the full set of weights.
Effects of changing the values¶
| Change | Result |
|---|---|
| Disabling expert parallel on decode | Each card has to load the full set of weights, so 234 GB does not fit into 144 GB and the instance cannot start. |
| Changing the PP degree | Prefill --max-num-seqs has to change with it. devices.npu.count is shared by both roles and must equal DP × TP × PP of each role, so decode's parallelism has to reach the same NPU count, or the render fails. In DRA mode the per-Pod NPU count comes from the ResourceClaimTemplate, so apply one with the new count under a new name and point devices.claimTemplateName at it. Recompilation is required. |
| Changing the DP degree on decode | The EPP targetPorts list (one port per decode DP rank) has to change with it. Prefill's parallelism, devices.npu.count, and the ResourceClaimTemplate have to reach the same NPU count, as for a PP change. Recompilation is required because expert parallel distributes the experts over the DP ranks. |
Role-specific --max-num-seqs values¶
| Role | Value | Meaning |
|---|---|---|
| prefill | 4 | A value dependent on the PP degree. It fills the four stages of PP4 to reduce pipeline bubbles, and does not represent concurrent processing capacity. |
| decode | 1 | A batch size of 1 per rank, a direct reflection of the latency-first principle. |
When the PP degree changes, this prefill value has to change with it. Specifying --max-num-seqs 4 with PP2 leaves more sequences waiting than there are stages, which increases latency. With --pipeline-parallel-size 2 or more, vllm-rbln checks at startup that --max-num-seqs is at least the PP degree, so PP8 needs a value of 8 or more.
Setting the decode value higher than 1 increases the per-rank batch size and reduces TPS/user. Total throughput can increase, but this design prioritizes per-user latency.
With DP, --max-num-batched-tokens (512) must be divisible by the decode value, or the engine refuses to start with max_num_batched_tokens must be divisible by max_num_seqs when DP enabled. Values of 1, 2, 4, and 8 work; 3 does not.
KV cache¶
--block-size 4096¶
Validated.
The KV cache is allocated in blocks of 4,096 tokens. Because sub-block prefix caching is enabled, the unit in which a prefix is reused is smaller than this block; see Prefix reuse unit of 512 tokens.
Prefix reuse unit of 512 tokens¶
Default configuration: the feature and accuracy validation confirmed the behavior; the effect of the sub-block size on performance was not measured.
With sub-block prefix caching (VLLM_RBLN_SUB_BLOCK_CACHE=1), the sub-block size becomes the --max-num-batched-tokens value (when VLLM_RBLN_SUB_BLOCK_SIZE is unset, as in the chart defaults), so the prefix reuse unit is 512 rather than --block-size (4096).
The router's hashing unit depends on autoTune. With autoTune: true (the default, kept by the chart and the recipes), the router replaces approx-prefix-cache-producer.blockSizeTokens and lruCapacityPerServer with the block size and block count in vllm:cache_config_info. vllm-rbln reports --block-size (4096) there even with sub-block prefix caching, so the router hashes prefixes in 4,096-token units and does not track a prefix shorter than one block, even though the engine can reuse it. The blockSizeTokens: 512 and lruCapacityPerServer: 1024 in the chart's values are fallbacks that apply only until the router first reads a Pod's metric; if a later read fails, the router keeps the last value it read. With autoTune: false, the router uses the configured blockSizeTokens, where 512 matches the sub-block unit, and lruCapacityPerServer must be set to the per-Pod block count in that unit. That configuration is Unverified.
KV block count¶
The engine derives the KV block count at startup from --gpu-memory-utilization. Use a smaller --gpu-memory-utilization only when a node reports Not enough memory for N blocks of KV cache or SYS_EBUSY: Lack of device memory during startup.
Warning
The block count must be at least ceil(--max-model-len / --block-size) + 1, because vLLM reserves one null block. At --max-model-len 204800 and --block-size 4096 that is 51 blocks.
KV capacity referenced by the router¶
Default configuration: the behavior was confirmed; the effect was not measured.
The Endpoint Picker (EPP) of the llm-d router keeps an index of the prefixes each Pod holds. In approx-prefix-cache-producer, lruCapacityPerServer sets how many entries that index keeps per Pod, counted in units of blockSizeTokens. The canonical configuration sets both values only as fallbacks for the time before the metric is read (blockSizeTokens: 512, lruCapacityPerServer: 1024). autoTune (on by default) reads each Pod's vllm:cache_config_info metric (CacheBlockSize, CacheNumBlocks) and replaces both per Pod; the fallbacks apply only before the router first reads that Pod's metric. With dynamic KV the block count is a runtime answer, so the metrics decide it. Because the derivation is per Pod, prefill and decode Pods each get a capacity that matches their own HBM, even though they differ.
For reference, in 4P4D on the Target Configuration with decode --max-num-seqs 1, the engines reported the HBM capacities below: num_gpu_blocks × --block-size in vllm:cache_config_info, after the dynamic KV resize at startup. The KV cache size line that the engine logs before warm-up is an estimate taken before that resize and reports a larger value.
| Speculative decoding | Pod | Engines | HBM capacity per engine (tokens) | HBM capacity per Pod (tokens) |
|---|---|---|---|---|
| EAGLE-3 (canonical) | prefill | 1 (PP4) | 1,212,416 | 1,212,416 |
| EAGLE-3 (canonical) | decode | 4 (DP4) | 315,392 | 1,261,568 |
| suffix decoding, n-gram | prefill | 1 (PP4) | 1,536,000 | 1,536,000 |
| suffix decoding, n-gram | decode | 4 (DP4) | 356,352 | 1,425,408 |
The EAGLE-3 draft head and its KV cache take part of the HBM, so the capacity is lower than with a method that loads no draft model. A larger decode --max-num-seqs lowers the decode capacity further, because each additional decode graph reserves memory: with EAGLE-3 at --max-num-seqs 8, a decode engine holds 282,624 tokens.
One limit: the metric covers HBM only. The RDS capacity of a prefill Pod (rds_max_chunks × LMCACHE_CHUNK_SIZE tokens per rank) is not reflected in the derived value, so with LMCache/RDS enabled the index undercounts what prefill actually holds: the router misses some prefixes that are still cached in RDS, which lowers the hit rate but produces no error. Unverified, because the Target Configuration validation ran without LMCache.
--kv-cache-dtype fp8¶
The bundled MiniMax-M2.7 and DeepSeek-V3.2 recipes use fp8 for the KV cache, and this design uses it too: the KV cache is stored in 8 bits, and because model weights and activations run as W8A16, the overall configuration is W8A16KV8. The per-token KV cache size of approximately 124 KiB assumes this state, and changing this argument requires recalculating the KV cache size in Coding Assistant on Rebel100™ › KV cache size and the KV capacity referenced by the router.
Speculative decoding¶
The canonical default is EAGLE-3 with num_speculative_tokens: 3, set on both roles: the draft head fills its own KV cache during the prefill forward pass, so prefill needs --speculative-config too. The speculation itself runs on decode.
EAGLE-3 is the default because its trained draft head keeps proposing on novel text, whereas suffix decoding and n-gram accept only where the output repeats the prompt or earlier responses. On a coding-assistant workload the output mixes both, so the trained head covers more of it; confirm the choice by measuring on your own workload.
MiniMax-M2.7 defines three MTP modules, but the published checkpoint does not include their weights, so a draft-model method has to use an externally trained draft head with published weights. The head is asherszhang/MiniMax-M2.7-EAGLE3-draft-vocab200k, published on HuggingFace for MiniMax-M2.7.
| Method | Status |
|---|---|
| EAGLE-3 | Validated (num_speculative_tokens: 3, including hidden state transfer). Canonical default |
| suffix decoding | Validated (4P4D) as {"method":"suffix"} with the vLLM defaults (see the note below) |
| n-gram | Validated (4P4D) |
suffix decoding parameters
The suffix run of the Target Configuration validation used the vLLM defaults, where num_speculative_tokens follows suffix_decoding_max_tree_depth (24), so vllm-rbln compiles a decode graph 25 tokens wide. A bounded form such as {"method":"suffix","num_speculative_tokens":3,"suffix_decoding_max_cached_requests":0} is Validated by the accuracy checks of the feature and accuracy validation; its acceptance rate was not measured.
chunk_mode for P/D KV transfer¶
Optional. Default configuration: the feature and accuracy validation confirmed the behavior; the effect on performance was not measured. By default, RblnNixlConnector sends the last block of a request in one transfer. With chunk_mode on, it sends the last block in chunks, which by default are the size of a prefill chunk (--max-num-batched-tokens).
Add "chunk_mode": true to the kv_connector_extra_config of RblnNixlConnector, with the same value on prefill and decode. The decode --kv-transfer-config becomes:
On a role that uses MultiConnector, such as prefill, add it only to the RblnNixlConnector entry of the connectors list; leave the RBLNLMCacheConnectorV1 entry unchanged.
chunk_tokens (in tokens) in the same kv_connector_extra_config changes the chunk size. The default 0 uses --max-num-batched-tokens. A value below --max-num-batched-tokens stops the engine from starting. The engine uses the smallest size at or above the given value that divides the block evenly; for example, 1500 with --block-size 4096 gives 2,048-token chunks.
The conditions for using it are as follows.
kv_buffer_devicemust berbln(D2D). Withcpu(host staging), the engine does not start.- The KV cache must have exactly one full-attention group. MiniMax-M2.7 meets this condition.
- When the engine cannot cut a block into chunks, it sends the block in one transfer even with
chunk_modeon, and recordschunk_mode registered no chunk rangein the startup log.
LMCache and RDS¶
Default configuration: the feature and accuracy validation confirmed the behavior; the effect was not measured. The Target Configuration validation ran without LMCache, and its workload did not produce enough KV reuse to characterize the effect of LMCache and RDS. In the P/D configuration, LMCache is wired into the prefill instances only, and decode uses NIXL alone. AGG recipes wire it into the decode Pods.
It is placed only on prefill because prefill produces the KV of the prompt and decode receives it over NIXL. Placing LMCache on decode would perform one more lookup and merely consume additional staging memory.
The behavioral characteristics are as follows.
- Stores are asynchronous, and write-back is not performed.
LMCACHE_LOCAL_CPU=false, so the CPU (DRAM) tier is not used.- When RDS is not available to the instance, startup does not fail and the instance reaches the Ready state without RDS. It runs degraded without any alert. The startup log records
[entrypoint] ⚠️ no RDS device (/dev/rblnfs*) in this container; after startup, check for that line or runkubectl -n <ns> exec <pod> -- sh -c 'ls /dev/rblnfs*'. - When
rds_max_chunksis reached or the NVMe is full, the least recently used chunk is evicted to make room; a store does not fail for lack of space.
CPU tier¶
Optional: on nodes where RDS is not available, host memory can serve as the KV offloading tier. Default configuration: the lmcache cpu mode of the feature and accuracy validation confirmed accuracy and cache reuse; the effect was not measured. The KV connector configuration (MultiConnector) is the same as for RDS; change only these values in modelserver.extraServeEnv.prefill.
| Environment variable | Value |
|---|---|
LMCACHE_LOCAL_CPU | true |
LMCACHE_MAX_LOCAL_CPU_SIZE | Capacity of the CPU tier in GB; 10.0 in the feature and accuracy validation |
LMCACHE_CHUNK_SIZE | A value that divides --block-size; 256 in the feature and accuracy validation |
LMCACHE_STORAGE_PLUGINS, LMCACHE_EXTRA_CONFIG | Set to null to remove them |
Keep LMCACHE_ENABLE_KV_EVENTS and LMCACHE_PRE_CACHING_HASH_ALGORITHM at the same values as the RDS configuration. Prefill's --gpu-memory-utilization 0.8 leaves chiplet 0 memory for RDS, so it is not needed when only the CPU tier is used. The CPU tier uses the prefill Pod's host memory, so it has to fit within the Pod's memory limit.
Compile cache invalidation cautions¶
The PP and DP degrees, --max-num-seqs, --kv-cache-dtype, the speculative decoding settings, and the SDK version are part of the cache key (see Compile Cache › Cache key). A changed configuration may require a cold compile even when the compile-cache PVC is preserved; review the startup budget in Startup and readiness probes before changing it. A startup error such as Not enough memory for N blocks of KV cache or SYS_EBUSY: Lack of device memory is diagnosed as a KV memory shortfall, not as evidence that the PVC must be deleted (see Failure response › Diagnosis by symptom).
Change impact summary¶
| Value changed | Item that has to change with it | Recompilation |
|---|---|---|
| PP degree | prefill --max-num-seqs; decode parallelism, devices.npu.count, and the ResourceClaimTemplate at the same NPU count | Required |
| DP degree | EPP targetPorts (one port per decode DP rank); prefill parallelism, devices.npu.count, and the ResourceClaimTemplate at the same NPU count | Required |
--max-num-batched-tokens | The engine's prefix reuse unit (sub-block size). autoTune does not follow it, because the engine reports --block-size; change EPP blockSizeTokens with it only when autoTune is off. Under DP, decode --max-num-seqs must divide it | Required |
--max-model-len | EPP maxPrefixTokensToMatch | Required |
--speculative-config (method, num_speculative_tokens) | The other role's --speculative-config, because EAGLE-3 runs on both roles | Required |
--block-size | EPP blockSizeTokens and capacity index, both re-derived by autoTune (see KV capacity referenced by the router); LMCACHE_CHUNK_SIZE, which must divide --block-size | Required |
--kv-cache-dtype | Per-token KV size; the EPP capacity index follows via autoTune | Required |
--gpu-memory-utilization (prefill) | rds_max_chunks in LMCACHE_EXTRA_CONFIG: each stored chunk holds 2 MiB of chiplet 0 memory per NVMe drive, so raising the utilization requires lowering the chunk cap | Required |
Related documents¶
- Coding Assistant on Rebel100™ › KV cache size - the per-token KV cache size
- Chart configuration reference › Key chart settings - the chart values that carry these arguments
- Validation and Limits - the validated serving configurations and features
- Configuration Guide - RBLN vLLM engine arguments and their constraints