TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

Measuring LoRA Adapter Serving Directly: Throughput Cost, Adapter Slots, and Dynamic Loading

Status: Draft (2026-10-07), based on actual measurements. Because the adapters are random weightscreated for performance testing, their output quality is meaningless, and only speed and resource behavior were measured. Calculated items are marked as "Calculated," and unmeasured items are marked as "Unmeasured." Writing Rule: Measured data is the baseline, and unmeasured items are marked as "Unmeasured."

Table of Contents

1. Why Serve LoRA

Fine-tuning a model for each use case requires loading the entire model into memory for each. LoRA keeps the base weights W as they are, trains two low-rank matrices (B, A) to change to W + (α/r)·B·A , so you can attach multiple small adapters to a single base model and use a different adapter for each request. This is why people try to serve customer-specific and task-specific models on a single GPU. vLLM documentation explains that adapters can be served per request with low overhead. This post measures what percentage that "low" overhead actually is in this environment.

2. Environment and Methodology

Item Value
GPU Single 8GB laptop-class GPU, no other tasks running
Server vLLM 0.31.0, Qwen3-1.7B(bf16), --max-model-len 4096, --max-num-seqs 64, --max-lora-rank 16
Adapter 3 LoRA adapters (a, b, c) created with PEFT. Rank 8, targeting the q, k, v, o projections of attention, lora_B initialized with random values from different seeds (standard deviation 0.02)
Adapter Size 3,211,264 trainable parameters, which is 0.19%of the 1,720,574,976 base model parameters (measured). Approximately 6.4MB in bf16 (calculated)
Requests Input Write a long story about a robot., 128 output tokens, temperature 0, ignore_eos, selecting adapters using the server's model name per request
Iteration Sending a batch of identical requests at once and calculating total throughput (number of output tokens ÷ time taken)

Pay attention to the number of concurrent requests. The tables in this post list the "number of requests sent at once" (3, 18, 48). Due to the argument names of the testing tool, we initially called it "concurrency 1, 16," but we corrected this after confirming that it was actually sending 3x the requests.

Because the adapters are random, their outputs are meaningless. Since the size and computational load of adapter matrices are independent of whether they are trained, speed and memory behavior are assumed to be identical to trained adapters, but this was not verified with trained adapters (unmeasured).

3. The Cost of Throughput

Identical requests were sent to the baseline server (LoRA disabled) and the LoRA-enabled server.

Requests Sent at Once Server Model Used by Requests Total Throughput vs. Baseline Median ITL
3 LoRA Off Base 199 tok/s Baseline 15ms
3 LoRA On Base (No Adapter) 200 tok/s +0.5% 15ms
3 LoRA On Adapter a 182 tok/s −8.5% 16ms
48 LoRA Off Base 2,667 tok/s Baseline 17ms
48 LoRA On Base (No Adapter) 2,664 tok/s −0.1% 17ms
48 LoRA On Adapter a 2,190 tok/s −17.9% 19ms
48 LoRA On Alternating a and b 2,323 tok/s −12.9% 20ms
48 LoRA On Alternating between a, b, and no adapter 2,346 tok/s −12.0% 20ms

Repeated test (5 times each, same server). 48 requests (3 times concurrency 16) were sent 5 times in shuffled order across three conditions: no adapter, adapter a, and alternating adapters a and b (--max-loras 2).

Condition Throughput (tok/s), 5 runs Median Vs. Baseline
No adapter 2,647, 2,658, 2,669, 2,663, 2,667 2,663 Baseline
Adapter a 2,183, 2,398, 2,390, 2,391, 2,390 2,390 -10.3%
Alternating adapters a and b 2,329, 2,330, 2,332, 2,329, 2,332 2,330 -12.5%

4. Adapter slots: When the number of adapters exceeds --max-loras ,

--max-loras is the maximum number of different LoRAs that can fit in a single batch(default 1). Initially, we wrote it as "the number of adapters that can be loaded on the GPU simultaneously," but after directly reading the source code (vllm/config/lora.py) of the vLLM 0.31.0 image used in this post, the description was "Max number of LoRAs in a single batch," and the number of adapters to place on the CPU side was a separate --max-cpu-loras(default is the same value as max_loras ). We sent 18 requests with 3 adapters all at once (2 repetitions per setting. While the values for both runs were often nearly identical, adapters a and b with 2 slots differed at 886 and 984).

Server Configuration No adapter Adapters a, b Adapters a, b, c
--max-loras 2 1,120 tok/s 886~984 tok/s 529 tok/s
--max-loras 4 1,131 tok/s 986~987 tok/s 950 tok/s

4-1. Running the same test in SGLang

We measured LoRA performance in SGLang 0.5.21 (--enable-lora --max-loras-per-batch N) using the same model and three identical random adapters (rank 16, 0.19% of parameters).

Test SGLang vLLM (Sections 3 & 4 above)
Concurrency 16 (48 requests), no adapter 2,544 tok/s (median of 3 server runs, 2,533~2,552) 2,664 (adapter-free requests on LoRA-enabled server)
Same load, adapter a 2,515 tok/s (-1.1%, median of 3 server runs, 2,509~2,518) 2,390 tok/s (-10.3%, median of 5 runs)
18 requests, mixing 2 adapters, 2 slots 1,045 tok/s (no adapter 1,027) 886~984 tok/s (no adapter 1,120)
18 requests, mixing 3 adapters, 2 slots 558 tok/s 529 tok/s
Same test, 4 slots 1,034 tok/s (median of 3 server runs, 1,030~1,038, first test 1,045) 950 tok/s

5. Time Taken to Load Adapters During Runtime

VLLM_ALLOW_RUNTIME_LORA_UPDATING=True after launching the server, I added adapter c with /v1/load_lora_adapter .

Item Result
Response of the load request LoRA adapter 'c' added successfully, 0.18 seconds for the entire call (including remote command execution overhead)
First requests right after loading 3 requests at 182 tok/s, same speed as adapter a

6. Takeaways for Production

  1. Measure the throughput cost of requests using adapters in advance. It was 8 to 18% in this environment and varies depending on the model and concurrency.
  2. --max-loras Match to the number of concurrently appearing adapters. If slots are insufficient, throughput drops to about half.
  3. Adapter deployment is lightweight, but uncontrolled loading is dangerous. Control it via pipelines and load only verified adapters.
  4. There was no cost to keeping LoRA enabled. Requests not using adapters were unaffected.
  5. Measurements must be retaken with trained adapters and larger models. The figures in this post were obtained from a small model (1.7B) and a 4B-FP8 instance with random adapters.

7. Potential Interview Questions

External Evidence: Verified with Papers and Official Materials

External figures had different model, GPU, and adapter configurations, so direct comparisons were not made; instead, only the consistency of direction and order of magnitude was judged.

Topic Source and Verified Location Verified Content and Conditions Relation to This Post
Size of LoRA Hu et al., "LoRA: Low-Rank Adaptation of Large Language Models", arXiv 2106.09685 (ICLR 2022), Abstract and Section 4.2 In GPT-3 175B, training parameters were reduced by up to 10,000x and checkpoint size from 350GB to 35MB (rank 4, applied only to query and value projections). The claim that inference latency does not increase holds true only for a single adapter merged into W0 + BA , and the paper notes as a limitation that mixing different adapters in a single batch is difficult in the merged state Supports. Our adapter is 0.19% of the base model (3,211,264 parameters, calculated from model config and matches). The 8.5 to 17.9% decrease in Section 3 is the cost of the approach where they are not merged and selected per request
Throughput of Multi-Adapter Serving Chen et al., Punica, MLSys 2024, arXiv 2310.18547, Section 7, Figure 11. Sheng et al., S-LoRA, MLSys 2024, arXiv 2311.03285, Section 7.2, Table 3 Punica: Single A100 80GB, Llama-2 7B/13B, rank 16. When using only the same adapter, throughput is about 8.4% lower for 7B and about 12.2% lower for 13B compared to backbone-only vLLM (calculated from paper figures), with an additional latency of about 2ms per token. S-LoRA: Keeping adapters in host memory and bringing only those for running requests to the GPU maintains throughput even when increasing adapters from 5 to 100, with a slight decrease Conditionally supports. The throughput decrease and order of magnitude for requests using adapters are the same. There are no external figures corresponding to "halving when slots are exceeded," and S-LoRA explains that the number of active adapters determines the cost, suggesting this phenomenon may be specific to vLLM's max_loras configuration
--max-loras Meaning vLLM 0.31.0 source config/lora.py, v1/core/sched/scheduler.py(read directly from the image used in this post) Number of different LoRAs in a single batch (default 1). When the limit is reached, requests for other adapters are skipped. max_cpu_loras is separate (same as default max_loras) Correcting the initial description. Section 4 above
Overhead and Runtime Loading vLLM documentation "LoRA Adapters" (dated 2026-09-28) States that adapters are served with low overhead on a per-request basis, without quantitative figures. VLLM_ALLOW_RUNTIME_LORA_UPDATING carries a warning not to use it in production unless it is an isolated, trusted environment, and specific reasons are not stated Conditionally supports. "Low overhead" was not small at 8.5 to 17.9% in this environment

Things Not Verified

References

Verified Version and Date

As of 2026-10-07. vLLM 0.31.0, PEFT 0.21.2, accelerate 1.15.0, Qwen3-1.7B (bf16).

Sign in to like

Comments

No comments yet.

Sign in to leave a comment