LoRA adapters are small, but serving them is not free
...which is exactly what the file size on disk won't tell you. A LoRA delta might be a few hundred megabytes riding a multi-gigabyte base checkpoint, and that ratio fools people into thinking adapter serving is nearly free. It isn't. Base weights get shared, but scheduling, batching, and cache identity don't shrink because the delta file did.
Picture one base model carrying half a dozen specialized tasks, each with its own adapter. Before touching a launch flag, name the number you're moving: first-token latency, jobs per hour, adapters resident, energy per task, or fewer corrections. "Make it faster" won't tell you when you're done, or when you've quietly traded away quality to get there.
Pin everything before you swap anything
Fix the model artifact, tokenizer, prompt template, runtime build, launch command, and sampling settings before comparing anything. Use real workload inputs, awkward ones included. Run cold once if production hits that path, then warm long enough to expose cache effects, queue depth, memory pressure, and thermal throttling. Measure merge versus dynamic-adapter serving separately, raw code or a server like vLLM: switching latency, memory, cross-adapter batching effects on throughput. Log phases, not one total: queue wait, load or activation, prefill, first token, decode rate, peak RAM and VRAM.
Speed on paper, sprawl underneath
Tokens per second is a diagnostic, not the answer. Count valid records per hour for automation, review-plus-correction time for coding, p50/p95 first-token latency for chat. A config winning a short warm run can lose once swaps and long prompts arrive. Watch the trap that eats multi-adapter setups: an adapter per prompt variation until routing becomes its own job. Local runtimes won't warn you, they just keep going: offloading layers, paging memory, missing cache, falling back to a generic kernel. That's how a degraded setup hides for weeks. Check the log and device placement, confirm the optimization is active for the shapes and context in use.
Change one thing, keep the receipts
A five-percent speedup that depends on an undocumented patch isn't a win, it's a debt with a delayed due date.
Change one variable at a time unless comparing whole systems, and keep the outputs, not just the metrics. Quantization, context compression, and sampling can make an answer worse while making it faster, so the quality gate runs on every candidate. Weigh operational cost too: startup, upgrades, rebuilding after a disk failure. Boring configurations age well.
Write down when to stop believing it
Adapters earn their keep on durable behavior shifts with a measurable gain, not a benchmark run once. Write it beside the workload, date, and reasoning, plus the retest trigger: new model family, driver update, longer contexts, different traffic mix. Skip that and old numbers turn into folklore nobody rechecks. Leave headroom: free memory for prompt variance, spare queue capacity so a batch job doesn't starve an interactive user, thermal margin too. Efficiency isn't maxing every resource, it's finishing the work on the least fragile setup that clears it.
Do this properly and you'll still guess sometimes. Production never quite matches what you benchmarked.