lmcache

Finding Reusable KV Caches Across a Fleet of Servers: LMCache’s MP (MultiProcess) Coordinator

2026-10-16

SSiddhant Ray

Introducing the MP Coordinator

TL;DR

MP servers store and move KV caches. The coordinator helps the fleet know which KV caches already exist.


In a distributed inference fleet, a local KV cache miss does not always mean the KV cache does not exist. The exact KV cache a request needs may already have been computed on a different process, GPU worker, or node. Recomputing it wastes GPU cycles. Reusing it first requires an answer to one question: does this KV cache already exist somewhere in the fleet, and if so, where?

LMCache’s MP Coordinator answers that question. LMCache’s MP (multiprocess) mode already moves KV cache management out of individual inference processes and into a standalone server. The coordinator extends that idea across the fleet: it keeps a lightweight view of which LMCache servers are alive and what cache state they report. KV data never flows through the coordinator, so it does not add another storage tier. It holds only the control-plane metadata needed to discover and manage reusable KV cache across servers.

This post explains why that split between metadata and data matters, how the coordinator builds its view of the fleet, and how you can try it yourself.

From process-local KV to MP mode

Traditionally, an inference engine manages its KV cache inside the engine process itself. This is simple, but it also ties the lifetime and visibility of cached KV to that process.

That becomes increasingly limiting as serving systems scale out.

Consider a node running several inference workers. Worker A may have already computed a long system prompt, retrieved document, or conversation history. If the next request containing the same context reaches Worker B, Worker B cannot necessarily reuse A’s state. The computation exists, but the cache is effectively siloed.

LMCache’s MP mode changes this architecture.

Instead of embedding all cache management inside each inference process, LMCache can run as a standalone MP server. Multiple vLLM processes can connect to the same server, allowing them to share a common cache service while isolating cache management from the inference engine itself. This gives LMCache an independent memory-management layer and lets cache capacity, storage tiers, and serving processes evolve separately.

Conceptually, the architecture moves from:

Three separate process boundaries, drawn as dashed boxes, stacked top to bottom. Each holds one vLLM process, A, B, or C, with a hairline arrow to its own KV cache, shown in teal. Nothing crosses from one boundary to another, so each process can reuse only the cache it computed itself.
Each vLLM process keeps its own KV cache, so context computed by one process is invisible to the others.

to:

vLLM processes A, B, and C stacked at the left, each joined by a two-way vermilion arrow, for KV data in flight, to one LMCache MP server drawn at double weight. Inside the server is a single teal block, the KV cache that all three processes now share. A note at the server's edge names the port the processes connect to, lmcache.mp.port 5555.vLLM processes A, B, and C stacked at the left, each joined by a two-way vermilion arrow, for KV data in flight, to one LMCache MP server drawn at double weight. Inside the server is a single teal block, the KV cache that all three processes now share. A note at the server's edge names the port the processes connect to, lmcache.mp.port 5555.
One LMCache MP server holds the KV cache for every process on the node, which removes the process boundary.

That removes one important boundary: the process boundary.

But a production fleet contains many nodes, and therefore many MP servers:

wo GPU nodes, A and B, side by side in dashed boundaries. Each node holds a stack of three vLLM processes joined by two-way vermilion arrows to its own LMCache MP server, which holds a teal KV cache. A vermilion request arrow enters MP server B from below. A dashed double-weight line marked with a question mark runs over the top of both nodes from MP server B to MP server A: nothing tells server B that the cache it needs may already exist on node A.
With an MP server on every node, the same question comes back one level higher: does the KV cache a request needs already exist on another node?

Now the same problem appears one level higher.

MP Server A may contain exactly the KV cache needed by a request arriving at Node B. How does the system know? That is the job of the MP Coordinator.


The coordinator is a directory, not a cache

The easiest way to think about the MP Coordinator is as a directory for the LMCache fleet.

Each MP server still manages its own cache and serves KV data. The coordinator maintains metadata describing the fleet: which servers are alive, what cache entries have been reported, and where those entries are located.

A simplified view looks like this:

The MP coordinator, drawn at double weight, holds four stacked parts joined by arrows: server registry, event gate, key directory, and a dashed optional blend index. Below it sit MP servers A and B, each holding a teal KV cache. Hairline arrows carry cache events from each server up into the event gate. A two-way vermilion arrow labeled KV data runs directly between server A and server B and never enters the coordinator.
The coordinator keeps only metadata, built from the servers’ cache events. KV data moves directly between MP servers and never passes through it.

The coordinator does not store or serve the KV caches themselves.

The coordinator is part of the control plane. Cache reads, storage operations, and peer-to-peer KV transfers remain in the MP server and storage layers.

That separation matters. Putting a centralized service directly in the KV data path would turn it into both a bandwidth bottleneck and a potential latency bottleneck. Instead, LMCache centralizes the comparatively small amount of information required to reason about cached state while keeping the much larger KV payloads on the data path where they belong.

Building a fleet-wide view

The coordinator builds this view in four steps.

1. Servers register and stay alive through heartbeats

An MP server configured with a coordinator URL registers itself with the coordinator and periodically sends heartbeats. The current default heartbeat interval is five seconds.

Registration is deliberately best-effort: an MP server keeps serving requests even if the coordinator is temporarily unavailable, so losing the control plane does not stop the data plane.

This gives the coordinator a continuously updated view of which cache servers make up the fleet.

2. Cache events describe how state changes

Knowing which servers exist is useful, but it does not tell us what they cache.

For that, MP servers can enable coordinator event reporting. Servers then report cache lifecycle events such as:

  • STORE: a cache object was added,
  • ACCESS: an existing cache object was used,
  • DELETE: a cache object was removed.

These events can be delivered directly over HTTP or through Kafka. The coordinator consumes them and incrementally updates its view instead of repeatedly scanning every cache server.

This distinction is important when deploying the coordinator: registration alone gives the coordinator fleet membership; event reporting gives it cache placement information.

3. The Event Gate makes the event stream usable

Distributed systems inevitably produce retries, restarts, delayed messages, and duplicated events.

Before cache events modify the coordinator’s state, they pass through an Event Gate. The Event Gate tracks the event sequence and incarnation associated with each server, allowing the coordinator to reject duplicate events and events belonging to stale server incarnations.

This prevents, for example, an event from an old server process from resurrecting cache state after that process has already restarted.

4. The Key Directory maps cache objects to placements

Events admitted by the Event Gate update the coordinator’s Key Directory.

At a high level, the directory maintains a mapping like:

KV cache
    ├── MP Server A / L1
    └── MP Server C / L2

A placement contains information such as the owning LMCache instance, storage tier, backend, and object size. The directory also keeps indexes that associate cached chunks with their token information.

The result is a fleet-wide answer to a question that would otherwise require probing every cache independently:

Where have we already seen this KV cache?


Exact reuse—and reuse beyond prefixes

For normal KV lookup, LMCache chunks a token sequence and derives cache keys from those chunks. The coordinator’s directory lookup can take the token sequence, derive the corresponding keys for complete chunks, and return the placements currently known for those keys.

Prefix caching works well when the cached content starts at exactly the same position in a new request. But useful context is not always reused as a prefix. A retrieved document, for example, may appear at one position in one prompt and somewhere else in another.

LMCache’s CacheBlend mechanism targets this form of non-prefix reuse. When the coordinator is started with Blend lookup enabled, it maintains an additional index over reported chunk contents. A query can then discover cached chunks that occur anywhere inside the new token sequence, together with their original and new positions.

The broader idea is useful: once reusable KV spans an entire fleet, finding reuse can become richer than asking whether a single local prefix happens to match.


Why the directory is intentionally “soft state”

A natural question is whether the coordinator needs a strongly consistent database of every KV cache in the fleet.

LMCache deliberately does not build one.

LMCache’s design documentation describes the Key Directory as eventually consistent soft state. Its answers are placement hints that must ultimately be validated by the server owning the cache object.

That tradeoff follows directly from the semantics of a cache.

If metadata is briefly stale and a supposedly cached object has already disappeared, the system can fall back to another copy or recompute it. A stale directory entry can hurt cache-hit rate or add lookup overhead, but it must not change the generated result.

This also changes how failures are handled.

When an MP server disappears or restarts, the coordinator can efficiently fence the L1 placements belonging to that server. The implementation maintains a reverse index specifically so that removing one server’s L1 state does not require scanning the entire fleet-wide directory. L2 state can persist independently and is removed through its own cache lifecycle events.

The coordinator gives up transactional consistency in exchange for metadata that is accurate enough to capture reuse, without putting consensus on the critical path of every cache operation.


How LMCache’s P2P path uses the MP Coordinator

LMCache’s P2P path also uses the coordinator, but the coordinator is not currently the lookup service for every P2P cache miss.

For P2P, the coordinator supplies fleet membership. MP servers discover peers through it, establish connections with those peers, and perform the actual lookup and transfer directly between servers. Through the P2P transfer engine (NIXL by default), the receiving server reads the KV data directly from the peer’s memory, over RDMA where the network supports it, and the tensors never pass through the coordinator.

So there are two related functions:

Coordinator
    ├── Who is in the fleet?
    ├── What cache placements have been reported?
    └── What reusable chunks can be found fleet-wide?

MP servers
    ├── Own the actual cache
    ├── Validate cache availability
    └── Move KV data between storage tiers / peers

Keep this boundary in mind when you deploy: the coordinator helps LMCache find and manage reusable state, and every byte of KV data stays with the MP servers.


Performance: increasing the reuse domain matters

The coordinator is primarily a metadata service, so its benefit should not be measured as “the coordinator makes a lookup N× faster.” Its value comes from enabling the serving system to capture KV reuse that would otherwise be hidden behind process or machine boundaries.

Existing LMCache results illustrate why expanding that reuse domain matters.

In LMCache’s MP-mode evaluation with Qwen3-235B-A22B-Instruct-2507-FP8 on eight H100 GPUs, replacing vLLM’s in-process KV offloading (50 GB of host memory per rank, 400 GB in total) with one shared LMCache MP server of the same 400 GB reduced mean TTFT from 3.98 seconds to 0.29 seconds, roughly 13.7× lower. P99 TTFT fell from 13.55 seconds to 1.30 seconds, while mean decoding speed increased from 9.81 to 37.47 tokens/s.

MetricvLLM in-process offloadMP modeImprovement
Mean TTFT3.98 s0.29 s~13.7×
P99 TTFT13.55 s1.30 s~10.4×
Mean decoding speed9.81 tok/s37.47 tok/s~3.8×

An earlier LMCache P2P experiment showed the same effect between inference instances. Two vLLM instances ran on separate GPUs of one host, and the second reused contexts the first had already cached. For the query round, mean TTFT was 0.490 seconds on the second instance against 2.028 seconds on the first, and round time was 7.964 seconds against 38.323 seconds, roughly 4× and 5× better. The authors called that workload contrived, with full reuse, and it predates the MP Coordinator architecture. Read these numbers as the value of cross-instance reuse, not as a coordinator benchmark.

The larger the useful reuse domain, the less often expensive prefill work needs to be repeated.

MP mode expands that domain across processes. Fleet-wide coordination makes it possible to reason about reuse across servers.


How to try it out

The quickest way to see the coordinator in action is to start an MP server with event reporting enabled and inspect the directory that the coordinator builds.

Use a current LMCache checkout and install it locally:

pip install -e .

Start the coordinator:

lmcache coordinator \
    --host 0.0.0.0 \
    --port 9300

Then start an MP server and connect it to the coordinator:

lmcache server \
    --host 127.0.0.1 \
    --port 5555 \
    --http-port 8080 \
    --l1-size-gb 20 \
    --eviction-policy LRU \
    --instance-id node-a \
    --coordinator-url http://127.0.0.1:9300 \
    --coordinator-event-reporting

The last flag is important. Without --coordinator-event-reporting, the server can register with the coordinator, but the coordinator does not receive the STORE, ACCESS, and DELETE stream required to build its fleet-wide key directory.

Now connect vLLM to the MP server using LMCacheMPConnector:

vllm serve <model> \
    --port 8000 \
    --kv-transfer-config '{
        "kv_connector":"LMCacheMPConnector",
        "kv_role":"kv_both",
        "kv_load_failure_policy":"recompute",
        "kv_connector_extra_config":{
            "lmcache.mp.port":5555
        }
    }'

After sending requests through vLLM, you can inspect the coordinator’s view of the fleet:

curl -s http://127.0.0.1:9300/instances \
    | python3 -m json.tool

and inspect reported cache entries:

curl -s \
  'http://127.0.0.1:9300/directory/keys?tier=l1&limit=20' \
  | python3 -m json.tool

To turn this into a real fleet experiment, start another MP server and vLLM instance with a different instance ID and point it at the same coordinator. Cache events from both servers will contribute to the same directory.

If you want to experiment with fleet-wide CacheBlend discovery, start the coordinator with:

lmcache coordinator \
    --host 0.0.0.0 \
    --port 9300 \
    --enable-blend-lookup

and keep event reporting enabled on the MP servers. For cross-node P2P transfer, the MP servers additionally need their P2P configuration and peer-accessible addresses; the coordinator handles peer membership while the actual lookup and KV transfer remain server-to-server.

Table of Contents

Share via:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

More from the blog

Discover more from LMCache Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading