Fleet Deployment: Multiple Robots, Shared Compute
One robot is a project. Five robots is a system. Twenty robots is an operation. Every team that has scaled past the first unit discovers that the engineering problem changes shape twice on the way up — once around three robots, again around ten. This article is about what changes, why the K-AI servers Kentino ships scale better than people expect, and the operational discipline you actually need on day 1 of fleet 2 of robot 3.
I01 covered the two-box problem for one robot and one server. K03 covered how vLLM cuts a model across GPUs. R08 made the case for why on-prem at all. This piece sits on top of all three and answers the next question: now you want to do it N times, what breaks?
The three regimes
There are three meaningful regimes of fleet size. The transitions between them are operational, not technical — the hardware looks similar; the way you run it does not.
| Fleet size | Regime | What it feels like | Dedicated robotics ops? |
|---|---|---|---|
| 1 robot | Project | One person can hold the entire stack in their head | No |
| 2–5 robots | System | You need scripts, dashboards, a deploy pipeline | Part-time |
| 6–20 robots | Operation | You need on-call, OTA, telemetry, SLOs, change windows | Yes, dedicated |
| 20+ robots | Production | You need an actual fleet management product | Team |
The blunt version: plan for a dedicated robotics-operations person around robot 3. The wall is not the network or the GPU server; the wall is human attention. One operator can manage two robots ad hoc. At five, the cadence of "this one's battery died, that one's lidar drifted, the third one's network flapped" is a full-time job, and pretending otherwise just burns the first hire on it part-time and badly.
The compute economics — what an 8-GPU K-AI actually serves
The number that should drive your sizing is concurrent VLM requests per second per robot, not robots-per-server. A robot is not a fixed load; it is a workload class. A picking task at 2 Hz is not the same as a navigation task at 0.5 Hz is not the same as a dialogue agent at 0.2 Hz.
Rough envelopes for an 8-GPU K-AI 256 with 8× RTX 5090 (FP8 / INT4 vLLM, single model, continuous batching on, prefix cache on; see I02 and K03):
| Workload class | Per-robot call rate | Per-call tokens | Concurrent robots on one 8× 5090 server |
|---|---|---|---|
| Small VLM scene tagging (Qwen2.5-VL 7B) | 2–5 Hz | 80–200 out | 16–24 |
| Mid VLM scene reasoning (Qwen2.5-VL 32B) | 0.5–2 Hz | 150–400 out | 8–14 |
| Large VLM (Qwen2.5-VL 72B INT4) | 0.2–1 Hz | 200–600 out | 4–8 |
| LLM planning (Llama 70B FP8) | 0.1–0.5 Hz | 300–800 out | 6–10 |
| VLA action policy (OpenVLA 7B) | 5–10 Hz | tokenized poses | 6–10 |
| Mixed agent (VLM 32B + LLM 70B + VLA 7B) | combined | combined | 3–6 |
These are envelopes, not promises. The numbers move with prompt length, image resolution, prefix-cache hit rate (much higher in fleet contexts because robots in the same building share environment context), and the exact mix of prefill vs decode. The pattern that matters is the shape: small-VLM-only workloads serve many robots per server; large-VLM-in-the-loop workloads serve few.
A real installation rarely runs one model. A fleet doing useful work usually wants a 72B VLM for scene reasoning, a 32B LLM for planning, and a small VLA for fine-grained motion intent. The 8× K-AI runs all three concurrently. With that mix, the realistic ceiling on one server is 4–6 humanoids doing closed-loop VLM work. That is the number to plan against — not the optimistic "we measured 24 concurrent 7B requests."
The batching lever (and why fleets are cheap)
The reason a single big server beats many small servers is continuous batching. vLLM holds a rolling batch of in-flight requests; on each forward pass, finished requests drop out and new requests join. Public benchmarks show vLLM achieving 2.3× the throughput of Text Generation Inference and 14–24× of naive PyTorch on the same hardware specifically because of this lever.
For a fleet, the effect compounds. Five robots hitting the same VLM endpoint with similar prompts produce a near-ideal batching pattern: most requests share a long system prompt (prefix cache 80–95% hit), arrival times are decorrelated enough that the batch stays full, and per-request cost amortises against shared prefill work.
1 robot = 1.00× compute baseline
2 robots = ~1.6× compute (batching helps)
4 robots = ~2.5× compute
8 robots = ~4.0× compute
Doubling robots is not doubling compute cost when they share a backend. This is the load-side argument for one big server over many small ones. Add it to the capex argument (one 8× 5090 box is cheaper than two 4× 5090 boxes by ~15–25% on the BOM) and the ops argument (one server to monitor, not two) and the math is one-sided for fleets up to about eight robots.
Past eight, you need a second server anyway, and the question becomes how to split traffic — covered below.
The architecture for a 3–8 robot fleet
- Inventory, telemetry, OTA updates, alerts
- Communicates over MQTT / HTTPS / gRPC
- /r01/ — Robot 01
- /r02/ — Robot 02
- /r03/ — Robot 03
- /r04/ — Robot 04
- Shared map server
- Task allocator
- Shared scene memory
- pgvector + Postgres
- VLM 72B — 4 GPUs
- LLM 70B — 2 GPUs
- VLA 7B — 1 GPU
- Embedding model — 1 GPU
Three planes on one physical host (under ~8 robots): fleet management, coordination, and inference. Each is logically distinct; split across hosts past that size.
Three planes, not one box. The fleet management plane is the operator-facing layer — robot inventory, telemetry, OTA updates, alerts. The coordination plane is the inter-robot layer — shared maps, task allocation, scene memory. The inference plane is the model-serving layer — vLLM behind a router. They run on the same physical K-AI host for fleets under ~8 robots, on separate hosts past that.
Request routing: what sits in front of vLLM
A naive setup with one vLLM endpoint, four robots, and TCP round-robin works for a week and then falls over the first time a request takes 8 seconds and the next four queue behind it. The router is the thing that prevents that.
Three options, in order of complexity:
Plain nginx with least_conn. Round-robin is wrong; you want least-active-connections so a slow request does not pull the whole fleet behind it. Five lines of config. Right answer for one model, one endpoint, two replicas. Does nothing for KV cache or prefix locality.
vLLM Router (Rust, released late 2025). Consistent-hashing on prompt prefix, so the same conversation lands on the same replica and the prefix cache stays warm. For a fleet where each robot has its own conversation but they all share a long system prompt, this is the right call. The policies are cache_aware, power_of_two, and round_robin; cache-aware is the default for production fleets.
llm-d on Kubernetes. Prefill/decode disaggregation, multi-replica scheduling, gateway inference extensions. The right answer when you have ≥4 replicas, mixed model types, and a Kubernetes-native ops team. Overkill for everyone else.
Session affinity is the subtle question. A robot conversing with a planning agent benefits from sticky routing to the same replica (prefix cache). A robot firing one-shot VLM scene tags does not — those are stateless, route them round-robin. The right answer is route by request type, not by client: planning to cache-aware, scene tagging to round-robin. The vLLM Router supports both via per-endpoint policy.
Scene memory: where each robot's context lives
A robot is not a stateless client. It remembers where it left the wrench yesterday, who walked through the door an hour ago, that the cardboard box on aisle 7 has been there for three days. That memory has to live somewhere, and the choice of where is one of the load-bearing decisions in a fleet design.
Three patterns:
Option A — per-robot pgvector on the server. Each robot has its own collection in a shared Postgres+pgvector instance. Memory is durable, queryable from the server side, accessible to fleet management. Simple, scales to dozens of robots on one Postgres. Privacy is the weak spot: every byte of every robot's memory is centralised.
Option B — on-robot scene memory with RAG to server. The robot keeps its own embeddings in a local sqlite-vss or DuckDB store. When it queries the server VLM, it ships the relevant retrieved chunks as part of the prompt. Memory is local and private; the network only sees what the robot chose to send. Better for sensitive deployments (medical, defence, anywhere the operator does not want raw memory leaving the robot). Costs more network bandwidth per call.
Option C — shared scene store with namespacing. All robots write to and read from one pgvector store, namespaced by site or task. Robot 2 can query "what did robot 1 see in the loading bay this morning?" and get a useful answer. This is the only option that supports actual collaborative tasks. It is also the option where a poisoned write from one robot pollutes the others' worldview.
The honest default for a 3–8 robot fleet is Option C with strict access control — robots write to their own namespace, read from a shared "world" namespace that is curated (the fleet manager promotes observations to it after validation). For privacy-sensitive deployments, Option B. Option A is the path of least resistance and is fine if collaboration is not a requirement.
Model sharing strategies
The default — one model serving N robots — is right for most fleets. Robots are doing similar tasks; the base model is the same; differences live in prompts and retrieved context, not in weights. This is the cheapest path and gives the highest batching efficiency.
Two cases where it breaks down:
Per-robot fine-tuned heads. Robot 1 lives in the warehouse and is fine-tuned for pallet handling. Robot 2 lives in the lab and is fine-tuned for instrument manipulation. You serve the same base VLM with different LoRA adapters loaded per request. vLLM supports multi-LoRA serving (--enable-lora --max-loras N) with a small per-request overhead and shared base-model batching. Useful when the fine-tunes are 0.1–1% of base weights (typical for LoRA) and you have 2–10 distinct adapters.
Specialty models per task class. A different model per task — Qwen2.5-VL for general scene reasoning, OpenVLA for grasping, a fine-tuned 7B for dialogue. Each model gets its own vLLM endpoint on its own GPU slice. Routes by request type. More VRAM, less batching per model, more operational surface. Right answer once you have validated that one model cannot do the job, not before.
Start with one model. Add LoRA adapters when you have a measured per-robot quality gap. Add specialty models when you have a measured per-task gap that LoRA does not close.
Robot fleet management (RFM) — pick a product
Building your own RFM is a trap most teams fall into once. The features are obvious in scope but expensive in reality: inventory, telemetry ingestion, time-series storage, OTA pipeline, alert routing, role-based access, audit logs, multi-tenancy if you have customers. A small team will build a version that works for one fleet and breaks under the second. Buy one of these instead and customise around it.
| Platform | License | Strengths | Picks for |
|---|---|---|---|
| Open-RMF | Open source | Interop across heterogeneous fleets, traffic management, resource arbitration (lifts/doors/corridors) | Mixed-vendor fleets, on-prem only, no SaaS fee |
| Formant | Commercial SaaS | Teleop, observability, data pipeline, predictive maintenance | Heavy observability/data-science teams |
| Freedom Robotics | Commercial SaaS | Lightweight, fast onboarding, pay-as-you-grow | SMB fleets, 1–20 robots, multi-brand |
| Boston Dynamics Orbit | Commercial | Native to Spot/Stretch/Atlas, site view, mission scheduling | Boston Dynamics shops |
| NVIDIA Isaac Mission Control | Open source (VDA5050) | Light VDA5050 fleet manager, ties into Isaac Cloud | NVIDIA-stack AMR fleets |
| Build your own | Your time | Fits exactly | Almost never the right answer |
Open-RMF has been managed by the Open Source Robotics Alliance since 2024 and handles task allocation, conflict resolution, and shared-infrastructure arbitration (lifts, doors, corridors). For a Kentino-style on-prem deployment with mixed-vendor robots — say one Unitree G1, one Booster T1, one Go2 quadruped, all on the same site — Open-RMF is the only credible open path. Formant and Orbit are excellent but they are SaaS and they prefer their own ecosystem.
The honest default: Open-RMF for on-prem mixed-vendor, Formant for hosted observability-heavy, Orbit for Boston Dynamics-only. Building your own RFM is wrong unless you are explicitly selling RFM as a product.
Multi-robot coordination on the wire
ROS 2 namespacing. Each robot runs its ROS 2 stack under a unique namespace (/r01/, /r02/, …). DDS topics, services, and parameters are namespaced too. Robots subscribe to peers' state topics (/r02/pose, /r03/pose) directly over DDS, no broker. ROS 2's DDS is peer-to-peer and scales fine to tens of robots on one LAN; past ~50, discovery traffic gets noisy and you want to either partition by DDS domain ID or move to ROS 2's discovery-server mode.
MQTT for telemetry up, commands down. ROS 2 / DDS is great for low-latency peer state on the LAN. It is not great for "send 0.5 Hz health telemetry to the fleet management cloud over a flaky LTE backhaul." MQTT is the right tool for that — lightweight, broker-mediated, QoS levels for guaranteed delivery, native support in every fleet platform. The typical split: DDS on the LAN, MQTT (or HTTPS) over the WAN.
Task allocation. Two approaches actually used in 2026 fleets:
- Central scheduler. The fleet manager assigns tasks based on robot availability, battery, location, capability. Simple, predictable, fits 90% of cases. Open-RMF does this out of the box.
- Auction-based. Robots bid on tasks based on a cost function (distance, battery, current load). The lowest bid wins. Better for heterogeneous fleets or dynamic environments. Recent work shows auction methods achieving ~12% energy savings over nearest-task allocation on fleets of 2–20 robots. Worth the complexity at fleets of 10+; overkill below.
Collision avoidance. Each robot publishes its pose at 10 Hz; each robot subscribes to peer poses. Local planners account for peer trajectories. For fleets where two robots routinely share a 1 m² workspace, you also need a coordination layer (Open-RMF's traffic management is the canonical answer).
Failure handling at fleet scale
The principle is simple: failures should be isolated, degraded modes should be graceful, recovery should be automatic. The practical patterns:
One robot dies, others continue. Every robot is autonomous on its on-board compute for safety and reactive perception. Loss of one robot is loss of one robot — peers do not block waiting for it. The fleet manager marks it down, reallocates its tasks, alerts a human.
Inference server fails. Every robot should be able to fall back to on-board-only mode when the server is unreachable: no large VLM, no long-horizon planning, but local control, obstacle avoidance, and pre-loaded mission steps still work. The robot effectively becomes "blind to language" but does not crash. Plan for this; test it monthly with a deliberate server-side firewall block.
Inference server rolling update. Two replicas behind the vLLM Router; drain one, redeploy, verify, drain the other, redeploy. Robots see no visible interruption because the router only drains replicas with no in-flight requests. Blue/green is the right call for model swaps too — load the new model on replica B, switch the router pointer, verify a few queries, retire replica A. Skipping the warmup step bites everyone exactly once (see I02 on the warmup gotcha).
The 1-of-N rule. At any moment in a fleet of N robots, assume one is degraded, one is offline, and one is doing something unexpected. Plan capacity for N-2 effective robots. If N-2 is not enough for the workload, the fleet is sized wrong.
Observability at fleet scale
The dashboard you actually want, in order of priority:
- Per-robot health. Battery, on-board GPU temp, last-seen timestamp, current task, last error. One row per robot, refresh every 5 seconds, red/yellow/green status. This is the first thing the operator looks at every morning.
- Per-robot latency to inference server. P50, P95, P99 round-trip time for each robot's VLM calls. Jumps in P99 are the leading indicator of Wi-Fi degradation, server overload, or a model swap that did not warm up.
-
Model serving queue depth.
vllm_num_requests_waitingper endpoint. Sustained non-zero is the signal that the fleet is outpacing the server. Alert at 10+ for over a minute. - Fleet utilisation heatmap. Which robots are busy, where in the building, doing what. Operational view; tells the manager whether the fleet is balanced.
- Model output sampling. A small fraction (1–5%) of model responses persisted to a review queue. Manual spot-check weekly. The only way to catch silent quality regressions.
Prometheus + Grafana for the metrics; the per-robot health view is usually whatever the RFM ships (Formant, Orbit, or your own Grafana). The relevant vLLM series are vllm:num_requests_running, vllm:num_requests_waiting, vllm:gpu_cache_usage_perc, vllm:time_to_first_token_seconds, vllm:time_per_output_token_seconds — these are the inference-side health story; DCGM exporter covers the GPU-side.
Cost scaling reality
| Fleet size | Recommended compute | Compute capex (approx €) | Per-robot capex |
|---|---|---|---|
| 1 robot | K-AI 96 (4× RTX 5090) | €25k–€35k | €25k–€35k |
| 2–4 robots | K-AI 256 (8× RTX 5090) | €50k–€70k | €12k–€35k |
| 5–8 robots | K-AI 256 (8× RTX Pro 6000 Blackwell) | €110k–€150k | €14k–€30k |
| 9–16 robots | 2× K-AI 256 + DP routing | €220k–€300k | €14k–€33k |
| 17–30 robots | 3–4× K-AI 256 + load balancer + RFM | €450k–€700k | €15k–€41k |
Two observations:
- Per-robot capex is roughly flat from 4 robots upward. Below 4, the fixed cost of the server dominates. Above 4, you are paying linearly for compute proportional to load. The sweet spot for the first server is 4–6 robots.
- Robot capex (which is separate and dominates) scales linearly. Compute is the small line item once the fleet is past ~3 robots. The single big cost lever is "do you need on-prem at all" (see R08), not "which size server."
The compute economics argue strongly for one big K-AI server serving 4–8 robots over multiple smaller servers. Two K-AI 256 boxes are worse than one K-AI 256 with 8× Pro 6000 for the same fleet up until you hit a server-capacity ceiling that triggers DP=2. The cross-over is workload-specific but lands around 7–9 robots on heavy VLM-in-the-loop work.
The honest take
Fleets above five robots are a different operational discipline from single units. They are not "five times a one-robot project". They are a different shape of project where:
- Compute is a small line item; operations is the big one
- The bottleneck is usually a human one (the manager's attention) before it is a technical one
- Wi-Fi and power planning bite three times harder than at fleet size 1
- The cost of a per-robot fine-tune is real; the cost of model degradation across the fleet is real-er
- Building your own RFM is almost always wrong; pick one and customise
The compute side of the problem is genuinely solved by 2026. vLLM + a router + a well-sized K-AI server handles fleets up to about 8 humanoids on one box. Past that, scale via data parallelism (more servers behind the router) — covered in K03. The hard problems above fleet size 5 are operational, not architectural.
What to do next — a fleet rollout sequence
If you are scoping a fleet deployment, here is the sequence that has worked:
Phase 1: Start at 1.
Buy one robot, one K-AI 96 server (4× RTX 5090 or one Pro 6000), and stand up I01's reference architecture. Run it for two months. Measure call rates, latency, prefix-cache hit rate, sustained GPU utilisation. Do not skip this phase. Every team that has tried to go straight to 5 robots has paid for it.
Phase 2: Expand to 3.
Add two more robots on the same K-AI server. The server is sized for 4–6 robots, so headroom is fine. Add nginx (or vLLM Router) in front of vLLM with least_conn. Add per-robot namespacing in ROS 2. Stand up the first version of the RFM (Open-RMF or a SaaS). Hire a part-time robotics ops person; promote them to full-time by month 3. This phase reveals every operational gap the single-robot setup hid.
Phase 3: Expand to 10.
Upgrade the K-AI to 8× Pro 6000 Blackwell if you are running large VLMs, or add a second K-AI 256 in DP=2 behind the vLLM Router. Move scene memory to a dedicated Postgres host. Introduce blue/green model deploys. Formalise on-call. Add the model-output sampling pipeline. The robotics-ops person is now a team of two, and one of them is on-call.
Phase 4: Past 10.
You are now running a production system. The decisions stop being technical and start being product-shaped: how do you sell SLOs to the customer paying for the fleet, how do you bill compute back to business units, when do you outsource the operations layer to a Robot-as-a-Service vendor. This article does not cover that — at that scale you should be talking to your RFM vendor, not reading the wiki.
The shape of the curve is consistent: the wall is always operational, never compute. Plan for the people side first, the network side second, the GPU server side third. We have never seen a fleet hit a real compute ceiling before it hit an operational one.
Follow-ups in the series: the reference build with parts list and benchmarks (I05), the cost-per-million-tokens math (T02), and case studies (C-series). The clustering and routing internals sit in K03; the failure-handling discipline in K06; the edge-tier justification in R08.
This is part of the Kentino Wiki, a reference series on AI compute, robotics, and the systems that connect them. Comments and corrections welcome at info@kentino.com.