From AFD Experiment to an Evidence-Driven vLLM Roadmap
The vLLM AFD Plugin makes Attention and FFN independently deployable. The harder next step is making every compatibility, model, backend, and topology claim independently verifiable.
Why split Attention from FFN?
Mixture-of-Experts inference combines two workloads with different scaling pressures. Attention is stateful: it owns scheduling, sequence state, and the KV cache. The FFN or expert path is dominated by routed computation and all-to-all communication. A shared worker topology forces both paths into the same resource allocation even when their bottlenecks differ.
Attention–FFN Disaggregation (AFD) preserves vLLM's request-facing control plane while moving expert execution behind a narrow connector interface. Attention and FFN ranks can then scale independently, and backend-specific communication can evolve without leaking into the serving API.
Request path
Attention service
API, scheduler, batching, KV cache, model lifecycle, and sampling
Data path
AFD connector
Hidden states, routing metadata, graph state, and returned FFN outputs
Expert path
FFN service
Lightweight daemon for expert computation without request traffic or KV cache
FFN results return through the connector before the Attention path continues.
What the first release establishes
The plugin integrates through vllm.general_plugins and --additional-config, without modifying the vLLM source tree. Its current matrix includes NVIDIA GPU and Ascend NPU paths, synchronous decode and asynchronous prefill connectors, and wrappers for DeepSeek V2/V3-family and GLM MoE models.
Synchronous decode
P2P NCCL on GPU and CAMP2P/HCCL on NPU exchange activations and FFN outputs synchronously. Their current graph paths are decode-only.
Asynchronous prefill
CAM asynchronous dispatch and combine operators overlap Attention and FFN stages with AFD-managed MoE ubatching. Graph execution is not yet supported on this path.
Reading the architecture from the code
AFD is not implemented as one large fork of vLLM. It is a chain of deliberately small interception points: plugin registration selects AFD-aware workers and model classes; the Attention runner injects execution metadata; the model wrapper introduces the layer boundary; and a connector-driven FFN runner consumes that boundary.
| Source file | Runtime responsibility | Architectural consequence |
|---|---|---|
| afd_plugin/__init__.py | Plugin bootstrap | Registers AFD model architectures and installs narrow compatibility hooks through vllm.general_plugins. |
| afd_plugin/v1/worker/attention_model_runner.py | Attention control path | Builds per-stage AFD metadata, injects it into vLLM's ForwardContext, and sends DP shape metadata. |
| afd_plugin/model_executor/models/deepseek_v2.py | Layer split point | Constructs role-specific modules and replaces the ordinary layer loop with send/receive boundaries around FFN. |
| afd_plugin/v1/worker/ffn_worker.py | FFN service lifecycle | Starts the connector-driven daemon, rejects scheduler execution, and allocates no KV cache. |
| afd_plugin/v1/worker/ffn_model_runner.py | Expert execution | Iterates layer and microbatch stages, receives hidden states, calls compute_ffn_output(), and returns results. |
| afd_plugin/connectors/base.py | Backend-neutral contract | Defines the four tensor-transfer operations and the separate DP metadata control-plane interface. |
| afd_plugin/connectors/gpu/p2p.py | CUDA transport | Implements NCCL subgroup fan-in, token concatenation, output splitting, and graph-stable receive buffers. |
1. Bootstrap: change the model lifecycle, not the API
The package exposes afd_plugin:register_afd as a vllm.general_plugins entry point. Registration maps native architecture names to plugin-owned wrappers such as AFDDeepseekV3ForCausalLM. Worker initialization then rewrites the model configuration to select that registered architecture.
This is why clients still use vllm serve. The public engine and OpenAI-compatible endpoint remain on the Attention service; the substitution happens below the serving interface, at worker and model construction time.
vllm serve
└─ general_plugins entry point
└─ register AFD model architectures
└─ parse additional_config["afd"]
├─ role="attention" → AFDAttentionWorker
└─ role="ffn" → AFDFFNWorker
└─ rewrite model architecture → AFD model wrapper2. Role-specific construction removes unused state
The DeepSeek decoder wrapper does more than skip half of a normal forward pass. During construction, each role creates only the modules it needs. The Attention layer builds self-attention and request-facing state; the FFN layer builds dense MLP or MoE modules. On the FFN worker, get_kv_cache_spec() returns an empty mapping and sampling is explicitly unsupported.
| Ownership | Attention worker | FFN worker |
|---|---|---|
| Request lifecycle and scheduler | Owns | None |
| KV cache and attention | Owns | None |
| Embeddings, norm, residual, sampling | Owns | None |
| Dense or MoE FFN modules | Role-dependent | Owns |
| Expert execution loop | None | Connector-driven |
| Connector and transfer metadata | Sends / receives | Receives / sends |
One subtlety: normalization and other shared lifecycle components may exist on both role-specific wrappers where the upstream model-loading contract requires them. “Split” means role-required construction, not a blanket claim that every non-expert parameter exists on only one side.
3. One layer, end to end
The actual split point lives inside the model wrapper's layer loop. Attention computes through post-attention normalization, sends that hidden state to FFN, and later receives the expert result. The residual stays on the Attention side, preserving request-local transformer state.
Prepare step metadata
The Attention runner records token counts, stage IDs, graph flags, and a transaction ID in ForwardContext.
Receive the prior FFN result
From layer 1 onward, Attention first receives the previous layer's returned FFN tensor.
Run Attention locally
The wrapper executes input norm, self-attention, residual handling, and post-attention norm.
Dispatch the split tensor
The connector sends the normalized hidden states with layer/stage/token metadata.
Aggregate on FFN
The GPU P2P path concatenates tensors from the Attention peers mapped to the same FFN rank.
Compute experts
The FFN runner calls the model wrapper's compute_ffn_output(hidden_states, layer_idx).
Split and return
The connector slices the aggregate output by the original per-peer token lengths and sends each slice home.
Complete the model
After the last dispatch, Attention performs one final receive, then continues to final norm and sampling.
# Attention process
for layer in layers:
previous_ffn = receive_if_pending()
attn_state, residual = layer.compute_attention(previous_ffn, residual)
send_to_ffn(attn_state, layer_id, microbatch_id)
final_state = receive_last_ffn()
sample(final_norm(final_state, residual))
# FFN process: driven by connector metadata, not request scheduling
for layer_id in layers:
for microbatch_id in active_stages:
aggregate, transfer = receive_attention_states()
expert_output = model.compute_ffn_output(aggregate, layer_id)
split_and_return(expert_output, transfer.peer_token_lengths)4. The connector is a two-plane protocol
The connector abstraction separates tensor movement from execution coordination. The data plane has four symmetric operations; the control plane carries per-stage DP token counts and warmup or graph-capture state so the FFN side can allocate the correct buffers before tensors arrive.
Control plane
- • stage → DP token-count metadata
- • graph-capture and warmup flags
- • receive shape and reusable-buffer preparation
- • triggers the connector-driven FFN step
Tensor data plane
- send_attn_output()
- recv_attn_output()
- send_ffn_output()
- recv_ffn_output()
Each transfer carries backend-neutral layer_idx, stage_idx, and per-peer sequence lengths. Backends can attach their own transfer state without changing the model-facing call sites. That is what lets NCCL P2P, CAMP2P/HCCL, and asynchronous CAM share one layer loop.
5. GPU topology: fan in, compute, fan out
For P2pNcclAFDConnector, global ranks are ordered FFN first, then Attention. The current topology requires at least as many Attention ranks as FFN ranks and an integer ratio. Each FFN rank owns one subgroup of consecutive Attention peers.
The important systems effect is aggregation: FFN sees tokens from several independently scheduled Attention lanes as one expert batch. The cost is a round trip at every split layer. AFD wins only when improved expert utilization and independent capacity planning outweigh communication, synchronization, and the extra FFN devices.
6. Ubatching turns the round trip into a pipeline
A synchronous implementation that executes Attention, sends, waits for FFN, receives, and only then starts the next slice would serialize the new boundary. AFD's stage metadata and ubatch wrapper create multiple in-flight slices so Attention work for one stage can overlap FFN work for another.
Useful pipeline mental model
Here TA and TF are per-stage Attention and FFN times, m is the ubatch count, and L is the number of split layers. This simplified model, also used to reason about FastAFD-style pipelines, explains why balance matters: steady state is limited by the slower side. It is not a performance formula implemented by the plugin.
More stages are not automatically better. They create overlap but also multiply small-kernel launches, metadata handling, and graph shapes. The currently validated DBO path is intentionally limited to exactly two ubatches; the async CAM prefill path owns a separate ubatching mechanism and currently does not support graph execution.
7. The code makes invalid ownership fail fast
No scheduler-driven FFN
AFDFFNWorker.execute_model() raises instead of silently running request work on the expert service.
No FFN KV cache
The FFN worker returns an empty KV-cache specification and skips cache allocation.
No sampling on FFN
GPUFFNModelRunner.sample_tokens() raises; token selection remains request-local on Attention.
Exact role validation
Both model runners parse the same AFD config with an expected role, catching mismatched launches early.
Shape-checked transfers
Connector metadata validates the leading token dimension before send and return operations.
Backend isolation
Connector-specific configuration and transfer state stay behind the factory and base contract.
Early performance signals—and their limits
The announcement reports two focused experiments. They are useful because they expose both the opportunity and the main systems lesson: disaggregation only helps when the Attention-to-FFN allocation matches the workload.
| Experiment | Comparison | Reported result |
|---|---|---|
| Ascend synchronous decode | 64A16F versus EP64 | +11.3% tokens/s/die at 16K input; +9.0% at 32K |
| Ascend asynchronous prefill | AFD versus DP4PCP8 baseline at 12 req/s | Median TTFT from 15.1s to 8.0s, about 47% lower |
Read these as path validation, not universal speedups.
The decode study used simulated logical scale and forced expert balancing that changes model outputs. The prefill study used a reduced 10-layer model. A smaller 48A16F decode allocation also trailed the EP64 baseline, reinforcing that topology selection is part of the result.
Support is a stack, not a checkbox
The roadmap's most important idea is to replace a global “supported” label with three evidence layers. A successful import does not validate a model, and a successful launch does not validate a production topology.
Core compatibility
The plugin works with one exact vLLM version.
Minimum evidence
Contract tests, package build/install, plugin-disabled isolation, and pinned-version checks.
Model + backend
A named model works correctly on a named backend.
Minimum evidence
Model review, correctness or accuracy results, exact environment, and backend-specific E2E tests.
Recipe + topology
A named topology has a reproducible, measured serving recipe.
Minimum evidence
Hardware and network disclosure, launch commands, correctness, performance, sustained load, and validation review.
Six workstreams, not six release phases
The roadmap is organized by dependency rather than calendar. Compatibility and delivery are foundational, while model, prefill, hardware, feasibility, and contributor-tooling work can advance in parallel when their prerequisites exist.
Compatibility, CI/CD, and releases
Define a maintainable vLLM alignment window, mirrored package versions, CPU-safe checks on every pull request, and tag-triggered GitHub and PyPI releases.
Model expansion
Adapt DeepSeek-V4 and GLM-5.2 through the native vLLM lifecycle, with backend validation and known exclusions documented per model.
Prefill and cache compatibility
Test chunked prefill and prefix caching independently and together, using long prompts and replayable coding-agent traces.
NVIDIA and AMD recipes
Build reproducible, topology-specific large-scale serving recipes with correctness, performance, sustained-load, and recovery evidence.
Kimi-K3 feasibility
Treat heterogeneous-attention prefill as a study first, and promote it to a support target only when measured goodput and tail TTFT justify it.
Repository-backed agent skills
Create thin orchestration skills for upgrades, model adaptation, hardware recipes, E2E tests, and releases while keeping deterministic logic in the repository.
Measure realistic prefill, not just launch success
The prefill workstream proposes a four-mode matrix: chunked prefill and prefix caching are tested with both features off, each enabled independently, and both enabled together. Correctness comes before performance interpretation.
Fixed 16K, 32K, and 128K prompts isolate long-context behavior. Multi-turn coding-agent trace replay adds growing shared prefixes and incremental tool output—the pattern that real agent systems produce. Reporting should include failure or hang behavior, TTFT tails, SLO-constrained prefill goodput, and cache effectiveness, not only averages.
The takeaway
AFD creates a clean systems boundary: keep vLLM's scheduler and KV-cache-aware Attention path intact, then make expert compute independently deployable through connectors. The launch proves that this boundary can work across multiple backends and execution modes.
The roadmap defines what must happen next: narrow version contracts, backend-specific model evidence, reproducible topology recipes, realistic workload evaluation, and honest negative results. That evidence discipline is what can turn a promising experimental plugin into durable serving infrastructure.