llama-server flags I actually change (and the ones I don't)
llama-server ships somewhere north of a hundred flags, and if you read forums long enough you'll believe you need thirty of them. I've run it daily since March on the 3090 box. It sits under half my pipelines and every Ollama comparison I publish, and I change six. Here are the six, plus the two I ran for five weeks that did nothing at all, and how I finally caught them.
The six that earn their keep
llama-server -m qwen3-coder-30b-q4_k_m.gguf -c 32768 -ngl 99 -fa --cache-type-k q8_0 --cache-type-v q8_0 -ub 1024 --parallel 2
The -c flag is the one you feel first. Agent work wants 32k of context, and context is VRAM, so this is really a memory-budget dial wearing a convenience costume. -ngl 99 puts every layer on the card; when a model doesn't fully fit, I drop one quant level rather than split layers and watch tokens crawl. -fa turns on flash attention, a modest speed win on its own and the gate for the pair that matters: quantized KV cache. Setting both cache types to q8_0 roughly halves KV memory with no quality drop I've been able to detect, and at 32k on the 30B it bought back about 1.7 GB, and on a 24 GB card that's the difference between fitting and spilling. The arithmetic lives in the KV cache math post.
The last two: -ub 1024 raises the microbatch, which cut prefill on my long-paste workloads by about a third, and --parallel 2 gives the server two slots: one for me, one for whatever script is running that hour.
The --parallel fine print
The --parallel flag splits the context budget across slots. Run -c 32768 --parallel 4 and each request gets 8k, and nothing warns you. I learned that in April when my agent developed amnesia mid-task, and I spent an evening blaming the model before I read the slot lines in the server log properly.
Slots share the pie; they don't each get their own.
Five weeks of someone else's flags
Now the embarrassing part. In early May I lifted a nine-flag 'optimal 3090 settings' block from a forum thread (confident tone, plenty of upvotes) and ran it verbatim into mid-June. Then came a slow Sunday with llama-bench, toggling one flag at a time, three runs each. Two of the nine did nothing on my machine. -t 12 pins CPU threads, which is meaningless when -ngl 99 leaves zero layers on the CPU; -t 4, -t 12, and the default landed within 2% of each other, pure noise. --numa distribute is for multi-socket servers, and my single-socket desktop is not one. Another exact zero.
A flag list from a forum is a benchmark of someone else's box. llama-bench costs twenty minutes and answers for yours.
Neither flag hurt, and that's exactly the trap. Harmless flags survive forever because nothing breaks, and you carry them into every config you write for years, lucky charms with long option names.
What I deliberately leave alone
The sampling flags stay at their defaults because sampling belongs to the client, per request; a server shouldn't bake in a temperature opinion. --mlock did nothing measurable once the model was fully offloaded, so it went back in the drawer. Rope-scaling flags I refuse to touch: modern GGUFs carry the right values in metadata, and overriding them is how you get quietly wrong long-context behavior. And -b, the logical batch, stays put, because raising -ub was what moved prefill.
One honest caveat on all of it: llama.cpp moves fast enough that flags get renamed or re-defaulted every few months, so treat my June defaults as a starting grid to bench against and nothing more. Measure with your model on your card, since counting your own tokens is half the discipline, and if this level of fiddling sounds like a hobby you never asked for, that's the real case for Ollama, which sets most of these for you and charges a little control for the service. I priced that trade in ollama vs llama.cpp.