<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Throttle</title>
    <description>The latest articles on DEV Community by Throttle (@throttle_pro).</description>
    <link>https://dev.to/throttle_pro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4144776%2F6ee3ad5e-9f51-4a59-8b7f-25b2c4d71d6c.png</url>
      <title>DEV Community: Throttle</title>
      <link>https://dev.to/throttle_pro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/throttle_pro"/>
    <language>en</language>
    <item>
      <title>The FP8 trap: my GPU bill dropped 47% because the model was printing "!!!!!!"</title>
      <dc:creator>Throttle</dc:creator>
      <pubDate>Tue, 06 Oct 2026 03:02:25 +0000</pubDate>
      <link>https://dev.to/throttle_pro/the-fp8-trap-my-gpu-bill-dropped-47-because-the-model-was-printing--2ge0</link>
      <guid>https://dev.to/throttle_pro/the-fp8-trap-my-gpu-bill-dropped-47-because-the-model-was-printing--2ge0</guid>
      <description>&lt;p&gt;I had one hour on an AMD MI300X and one question: what does a token actually cost on it?&lt;/p&gt;

&lt;p&gt;One GPU, vLLM's ROCm build, Qwen2.5 at 7B, 32B and 72B. Thirty-two requests in flight, 256 output tokens max, priced at the $2.99/GPU-hr list rate. Every number below is wall-clock time × that rate ÷ tokens produced.&lt;/p&gt;

&lt;p&gt;The baselines came out clean. Four repeat checks of each untouched config, so I'd know how much the machine wobbles on its own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7B: &lt;strong&gt;$0.227&lt;/strong&gt; per million output tokens&lt;/li&gt;
&lt;li&gt;32B: &lt;strong&gt;$0.77&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;72B: &lt;strong&gt;$1.67&lt;/strong&gt;, on a single GPU, which still surprises me a bit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 72B repeats agreed to within 0.4%. That's a very quiet machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious next move
&lt;/h2&gt;

&lt;p&gt;FP8 halves the bytes per weight. vLLM will do it for you on load with one flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vllm serve Qwen/Qwen2.5-72B-Instruct &lt;span class="nt"&gt;--quantization&lt;/span&gt; fp8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;32B: $0.77 → &lt;strong&gt;$0.449&lt;/strong&gt; (−41%)&lt;/li&gt;
&lt;li&gt;72B: $1.67 → &lt;strong&gt;$0.872&lt;/strong&gt; (−47%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three checks each, all well outside the noise. If I'd stopped there I would have written a very different post, and I'd have been telling you to cut your bill in half.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing that didn't fit
&lt;/h2&gt;

&lt;p&gt;I wasn't looking for a problem. I was reading the per-block lines and something was too neat.&lt;/p&gt;

&lt;p&gt;At temperature 0, with the same 32 prompts, BF16 32B wrote about 6,900 output tokens per block. FP8 wrote &lt;strong&gt;8,192&lt;/strong&gt; on every block. 8,192 is 32 × 256: every request ran all the way to the cap.&lt;/p&gt;

&lt;p&gt;Models don't suddenly get more talkative because you changed the weight format. So I asked both servers the same six questions.&lt;/p&gt;

&lt;p&gt;"Summarize the causes of World War I in about 80 words."&lt;/p&gt;

&lt;p&gt;BF16: an 89-token answer about nationalism, alliances and an archduke.&lt;/p&gt;

&lt;p&gt;FP8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…for all 256 tokens.&lt;/p&gt;

&lt;p&gt;It was cheaper per token because it was producing junk tokens very quickly. The cost number was accurate. It was just measuring the wrong thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was real
&lt;/h2&gt;

&lt;p&gt;Same idea, done properly: checkpoints that were quantized ahead of time and published (RedHatAI's &lt;code&gt;Qwen2.5-*-Instruct-FP8-dynamic&lt;/code&gt;). This time I checked the answers &lt;em&gt;first&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;They were right. 17 × 23 = 391. "Où est la gare ?" Sensible summaries. Output length matched BF16 within about 1% (72B: 6,361 vs 6,328 tokens per block).&lt;/p&gt;

&lt;p&gt;Then the cost, three checks each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;BF16&lt;/th&gt;
&lt;th&gt;FP8 (pre-quantized)&lt;/th&gt;
&lt;th&gt;change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7B&lt;/td&gt;
&lt;td&gt;$0.227/M&lt;/td&gt;
&lt;td&gt;$0.185/M&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−18%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;72B&lt;/td&gt;
&lt;td&gt;$1.67/M&lt;/td&gt;
&lt;td&gt;$1.13/M&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−32%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Noise bound under 3% on 7B and under 1% on 72B. So the real answer is about a third off a 72B on one MI300X. That's a smaller number than 47%, and you can actually use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule I'm keeping
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A cost-per-token number on its own can't tell a cheaper model from a broken one.&lt;/strong&gt; Before you trust a saving, check that the model is still doing the same work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Output length.&lt;/strong&gt; If average tokens per answer jumps, or suddenly everything hits &lt;code&gt;max_tokens&lt;/code&gt;, stop. Nothing else needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A handful of fixed prompts at temperature 0.&lt;/strong&gt; Read them. Takes a minute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeat the baseline.&lt;/strong&gt; If you don't know how much your server wobbles untouched, you can't tell a 5% win from Tuesday.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Number 1 is the cheap one, and the data for it is already sitting in your benchmark output. I'm building it into the tool I used here: if output length shifts between a baseline and a change, it says OUTPUT CHANGED instead of CHEAPER. That's coming in the next release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats, honestly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One session, one workload: short prompts, 256 output tokens, concurrency 32. Long-context or long-output traffic will behave differently.&lt;/li&gt;
&lt;li&gt;On 72B, the FP8 server ran on the VM's second GPU and the baseline on the first. Same card model, not literally the same card.&lt;/li&gt;
&lt;li&gt;I only sampled the broken on-the-fly 72B by output length, not by reading answers. On-the-fly FP8 on 7B was fine (6 of 6 answers correct, −18%).&lt;/li&gt;
&lt;li&gt;Six prompts is a sanity check, not an accuracy benchmark. If FP8 matters to your product, run your own evals.&lt;/li&gt;
&lt;li&gt;Prices are the provider's list rate. Tokens and time are measured.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't know yet whether the on-the-fly FP8 behaviour is specific to this ROCm image or to larger Qwen2.5 models. If you've seen it, tell me.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Measured with &lt;a href="https://github.com/KushagraKanaujia/throttle" rel="noopener noreferrer"&gt;Throttle&lt;/a&gt;, an open-source CLI that prices your inference in $/M tokens with confidence intervals and refuses to call a change a win inside your own noise. &lt;code&gt;pipx install throttle-pro&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>gpu</category>
      <category>mcp</category>
      <category>amd</category>
    </item>
    <item>
      <title>I rented an A100 to test one vLLM flag</title>
      <dc:creator>Throttle</dc:creator>
      <pubDate>Thu, 01 Oct 2026 03:01:41 +0000</pubDate>
      <link>https://dev.to/throttle_pro/i-rented-an-a100-to-test-one-vllm-flag-bcl</link>
      <guid>https://dev.to/throttle_pro/i-rented-an-a100-to-test-one-vllm-flag-bcl</guid>
      <description>&lt;p&gt;I rented an A100 for under an hour to answer one question.&lt;/p&gt;

&lt;p&gt;Does a single vLLM flag really change what a token costs?&lt;/p&gt;

&lt;p&gt;The flag was &lt;code&gt;max_num_seqs&lt;/code&gt;: how many requests the server works on at once. I set it to 1, which is a deliberately bad setting, and then to 8. Same GPU, same model (Qwen2.5-0.5B), same prompts, eight requests in flight the whole time.&lt;/p&gt;

&lt;p&gt;The obvious way to test this is: run the old setting, run the new one, compare. I don't trust that anymore. I once watched a server I hadn't touched "get" 27% more expensive between two runs. GPUs warm up, other work comes and goes, and a single before/after quietly bakes all of that into your answer.&lt;/p&gt;

&lt;p&gt;So I interleaved it. Six runs, alternating the order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;baseline → change → baseline
change → baseline → change
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the machine drifts during the session, the drift lands on both sides instead of making one look better.&lt;/p&gt;

&lt;p&gt;Here's what came back, in dollars per million output tokens at $1.39/hr:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max_num_seqs=1   $0.748   $0.746   $0.745
max_num_seqs=8   $0.237   $0.229   $0.237
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six runs, two tight clusters, no overlap. About &lt;strong&gt;68% cheaper per token&lt;/strong&gt;, and it held every single time.&lt;/p&gt;

&lt;p&gt;Two honest caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A baseline of 1 is unrealistically bad. Nobody should run production like that. The point was to prove the method, not to promise you 68%.&lt;/li&gt;
&lt;li&gt;It's a 0.5B model. Bigger models, longer prompts and real traffic will give you a different number. That's exactly why you measure your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What surprised me most wasn't the drop. It was how calm the numbers became once the runs were interleaved. Same server, same day, no drama.&lt;/p&gt;

&lt;p&gt;I turned this into a small open-source tool so I'd stop doing it by hand. It measures cost per million tokens with confidence intervals, and it only says CHEAPER when a change actually beats the noise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;throttle-pro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All six raw runs are public, if you want to check my math.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KushagraKanaujia/throttle/tree/main/validation/golden-live-20260817" rel="noopener noreferrer"&gt;The raw artifacts&lt;/a&gt; · &lt;a href="https://github.com/KushagraKanaujia/throttle" rel="noopener noreferrer"&gt;Throttle on GitHub&lt;/a&gt; · &lt;a href="https://www.throttle-pro.com" rel="noopener noreferrer"&gt;throttle-pro.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>llm</category>
      <category>performance</category>
    </item>
    <item>
      <title>What does one token actually cost you?</title>
      <dc:creator>Throttle</dc:creator>
      <pubDate>Thu, 01 Oct 2026 02:56:10 +0000</pubDate>
      <link>https://dev.to/throttle_pro/what-does-one-token-actually-cost-you-3b0</link>
      <guid>https://dev.to/throttle_pro/what-does-one-token-actually-cost-you-3b0</guid>
      <description>&lt;p&gt;I rent GPUs by the hour.&lt;/p&gt;

&lt;p&gt;For a long time I couldn't tell you what a single token cost me. I knew the hourly rate, and I knew the API providers' price sheets. The number in between, &lt;em&gt;my&lt;/em&gt; cost per million tokens on &lt;em&gt;my&lt;/em&gt; server, I was guessing.&lt;/p&gt;

&lt;p&gt;Turns out almost everyone self-hosting is guessing too.&lt;/p&gt;

&lt;p&gt;The math itself is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ per million tokens = ($/hr ÷ 3600) ÷ tokens per second × 1,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hard part is the "tokens per second". It moves with everything: batch size, a vLLM flag, a quantization, the engine version, the GPU, even what else the machine is doing.&lt;/p&gt;

&lt;p&gt;So I started measuring it properly. A few things surprised me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The same server doesn't give the same number twice.&lt;/strong&gt; I ran one check four times on an Ollama box I hadn't touched. It came back $8.77, $8.86, $11.26, $10.02 per million tokens. Had I changed a setting between runs three and four, I'd have happily told you it saved 11%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One number is not a measurement.&lt;/strong&gt; You need repeat runs, a confidence interval, and a noise floor. If a change doesn't beat the noise, the honest answer is "no winner".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When a change is real, it's obvious.&lt;/strong&gt; On an A100 with vLLM, moving &lt;code&gt;max_num_seqs&lt;/code&gt; from 1 to 8 took output cost from $0.746 to $0.234 per million tokens, holding across six interleaved runs. That baseline was deliberately bad. The point isn't the 68%; it's that you can finally &lt;em&gt;see&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching quietly lies.&lt;/strong&gt; Send the same prompts twice and a prefix cache makes run two look cheaper than it is. Every request needs to be cold unless you're measuring the cache on purpose.&lt;/p&gt;

&lt;p&gt;I got tired of doing this by hand, so I built a small tool that does it: measure, change one thing, measure again, and tell me CHEAPER, MORE EXPENSIVE or NO WINNER. It refuses to call a winner it can't prove, which turned out to be the whole point.&lt;/p&gt;

&lt;p&gt;It's open source and runs on your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;throttle-pro
throttle check &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:8000 &lt;span class="nt"&gt;--model&lt;/span&gt; &amp;lt;your-model&amp;gt; &lt;span class="nt"&gt;--gpu-hourly-rate&lt;/span&gt; &amp;lt;your &lt;span class="nv"&gt;$/&lt;/span&gt;hr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it three or four times before you change anything. The first surprise is usually how much your own server wobbles.&lt;/p&gt;

&lt;p&gt;If you're self-hosting and you've made a change you're not sure paid off, I'd genuinely like to hear about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KushagraKanaujia/throttle" rel="noopener noreferrer"&gt;Throttle on GitHub&lt;/a&gt; · &lt;a href="https://www.throttle-pro.com" rel="noopener noreferrer"&gt;throttle-pro.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>selfhosted</category>
      <category>startup</category>
    </item>
    <item>
      <title>I changed nothing and my LLM server got 27% more expensive</title>
      <dc:creator>Throttle</dc:creator>
      <pubDate>Sat, 26 Sep 2026 19:38:35 +0000</pubDate>
      <link>https://dev.to/throttle_pro/i-changed-nothing-and-my-llm-server-got-27-more-expensive-4i1j</link>
      <guid>https://dev.to/throttle_pro/i-changed-nothing-and-my-llm-server-got-27-more-expensive-4i1j</guid>
      <description>&lt;p&gt;I ran the same cost check four times in a row against a server I didn't touch. Same model, same machine, same prompts, same settings. This is what came back, in dollars per million output tokens:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;$/M output tokens&lt;/th&gt;
&lt;th&gt;95% CI&lt;/th&gt;
&lt;th&gt;Change vs previous run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$8.77&lt;/td&gt;
&lt;td&gt;$8.19 to $9.35&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;$8.86&lt;/td&gt;
&lt;td&gt;$7.80 to $9.93&lt;/td&gt;
&lt;td&gt;+1.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$11.26&lt;/td&gt;
&lt;td&gt;$10.31 to $12.21&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+27.1%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;$10.02&lt;/td&gt;
&lt;td&gt;$7.41 to $12.62&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−11.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run 3 says the server got 27% more expensive. Run 4 says it then got 11% cheaper. Nothing changed.&lt;/p&gt;

&lt;p&gt;If I had changed a flag between run 2 and run 3, I would have blamed the flag and rolled it back. If I had changed one between run 3 and run 4, I would have posted an 11% saving in Slack. Both would have been wrong, and both would have looked like data.&lt;/p&gt;

&lt;p&gt;This post is about why that happens and the rule I now apply before believing any before/after cost number. The tool in the output below is &lt;a href="https://github.com/KushagraKanaujia/throttle" rel="noopener noreferrer"&gt;Throttle&lt;/a&gt;, an open-source CLI I'm building, but the rule doesn't depend on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;A MacBook running Ollama locally with &lt;code&gt;llama3.2:3b&lt;/code&gt;. Each check sent 3 blocks of 4 requests at concurrency 2, capped at 64 output tokens, temperature 0, with the same 8 built-in prompts and one warm-up request. All four checks finished within about 70 seconds of each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;throttle check &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:11434 &lt;span class="nt"&gt;--model&lt;/span&gt; llama3.2:3b &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--gpu-hourly-rate&lt;/span&gt; 1.50 &lt;span class="nt"&gt;--label&lt;/span&gt; same &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--blocks&lt;/span&gt; 3 &lt;span class="nt"&gt;--requests-per-block&lt;/span&gt; 4 &lt;span class="nt"&gt;--concurrency&lt;/span&gt; 2 &lt;span class="nt"&gt;--max-tokens&lt;/span&gt; 64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The $1.50/hour GPU rate. A laptop has no GPU invoice, so I picked and ran Throttle on runpod on different GPUa labels it ASSUMED everywhere it appears. Tokens and time are measured.&lt;/p&gt;

&lt;p&gt;The cost math is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$/M output tokens = hourly rate × wall-clock hours ÷ output tokens × 1,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every block in all four runs produced exactly 256 output tokens (4 requests × 64 tokens). So the only thing that moved the price was time. The three blocks of run 1 took 5.53 s, 5.24 s and 5.40 s. The blocks of run 3 took 7.09 s, 7.02 s and 6.65 s. Same tokens, about 30% more seconds, about 27% more dollars per token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the same server swings
&lt;/h2&gt;

&lt;p&gt;A cost measurement is a timing measurement, and timing on a real machine depends on everything else the machine is doing: other processes, background indexing, thermal state and clock speed, memory pressure, OS scheduling. On a shared cloud node you can add noisy neighbours and other tenants on the same host or network.&lt;/p&gt;

&lt;p&gt;I didn't instrument the laptop during these runs, so I can't tell you which of those it was. That's the point. Most of the time you won't know either, and a single before/after pair can't tell load from a real change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the confidence interval didn't save me
&lt;/h2&gt;

&lt;p&gt;Each check reports a 95% confidence interval across its blocks. Look at runs 1 and 3: $8.19 to $9.35, then $10.31 to $12.21. The intervals don't overlap. The common rule of thumb ("non-overlapping intervals means a real difference") would call run 3 a real 27% regression.&lt;/p&gt;

&lt;p&gt;The interval answers a narrower question than it looks like. It's computed from the blocks inside one run, so it describes the wobble over about 20 seconds. It can't see drift between runs, because every block in a run shares the same conditions. If the whole machine is 30% slower for a minute, all three blocks are slower together and the interval stays tight around the wrong number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure the noise you are actually exposed to
&lt;/h2&gt;

&lt;p&gt;The fix is to measure run-to-run noise directly: run the unchanged config a few times, and see how much whole checks disagree with each other.&lt;/p&gt;

&lt;p&gt;Say the relative standard deviation between repeat checks of one config is SD. The difference between two single checks then has a standard deviation of √2 × SD, because each check carries its own noise. With only a handful of repeats you use Student's t instead of 1.96, with degrees of freedom from the repeats. That gives a 95% bound on how far apart two checks of the &lt;strong&gt;same&lt;/strong&gt; config can land:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;noise bound = t(0.975, df) × √2 × SD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, runs 1 to 3 were three checks of the unchanged config: $8.77, $8.86, $11.26. Their relative SD is 14.6%, with 2 degrees of freedom, where t is 4.303:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4.303 × 1.414 × 14.6% ≈ 89%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Throttle prints 89.1% because it uses the unrounded SD. Run 4 came in 11.0% below run 3. That's well inside ±89.1%, and the two intervals overlap as well, so this is the verdict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;before: $11.26/M output tokens (95% CI $10.31 to $12.21)
after:  $10.02/M output tokens (95% CI $7.41 to $12.62)
change: -11.0%
noise floor: calibrated: bound 89.1% (t x sqrt(2) x 14.6% run-to-run SD, 2 df)
Verdict: NO WINNER, the change (-11.0%) is not larger than the run-to-run
noise bound (89.1% = t x sqrt(2) x 14.6% run-to-run SD, 2 df); and the 95%
confidence intervals overlap, so the difference is within measurement noise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What about the +27.1% at run 3? Throttle didn't call it anything. With fewer than three earlier checks of the same config there's no noise estimate at all, so runs 2 and 3 both came back as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Verdict: NOT CALIBRATED — run-to-run noise unknown. Two checks at different
times can differ from load alone. Run 'throttle check' at least 3 times without
changing anything (within 24 h) to measure your noise, or use 'throttle golden'
for a counterbalanced decision.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I built it that way because refusing to answer beats a confident wrong answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  An 89% bound looks bad, and it's still the honest answer
&lt;/h2&gt;

&lt;p&gt;A bound of ±89% means these three repeats can't resolve any realistic config change, and that's true. One slow run out of three blew the SD up, and with 2 degrees of freedom t is large. The bound is saying: on this machine, right now, you don't know enough to judge a change.&lt;/p&gt;

&lt;p&gt;You can tighten it in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More repeats.&lt;/strong&gt; t falls quickly with degrees of freedom: 4.30 at 2, 2.57 at 5, 2.23 at 10. More checks also give a better SD estimate, so one slow run matters less.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A quieter, longer measurement.&lt;/strong&gt; Close what else is running, use longer blocks, and measure at the concurrency you run in production. Noise you remove is noise you don't have to bound.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a decision you'll act on, like which config goes to production, don't compare two sequential runs at all. Interleave them (baseline, candidate, baseline, candidate, baseline, candidate) so drift hits both sides equally. I wrote up a real six-run example on an A100 in &lt;a href="https://www.throttle-pro.com/blog/one-vllm-flag-counterbalanced-benchmark" rel="noopener noreferrer"&gt;One vLLM flag, −68.6% cost per token&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do now
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run the unchanged config at least three times first, within the same day.&lt;/li&gt;
&lt;li&gt;Change one thing.&lt;/li&gt;
&lt;li&gt;Believe the change only if it's larger than the run-to-run noise bound &lt;strong&gt;and&lt;/strong&gt; the 95% intervals don't overlap.&lt;/li&gt;
&lt;li&gt;Otherwise it's NO WINNER. Don't write the Slack message.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;This was a laptop, a 3B model, a short workload and an assumed GPU rate. The size of the swing is specific to that machine on that morning. Your servers will have their own noise, which is exactly why you have to measure it rather than borrow mine.&lt;/p&gt;

&lt;p&gt;These runs used Throttle 0.4.0, which repeats identical prompts, so the prompt cache was warm in all four runs. That rules out the cache as the cause of the swing, since it was the same in every run. Since 0.4.1, Throttle tags every request so a prefix cache can't make later checks look cheaper, and &lt;code&gt;--warm-cache&lt;/code&gt; measures a warm cache on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;throttle-pro
throttle demo      &lt;span class="c"&gt;# no GPU needed; every number is SIMULATED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then point &lt;code&gt;throttle check&lt;/code&gt; at your own vLLM, SGLang or Ollama endpoint and run it three times before you change anything. If you get an interesting result, &lt;code&gt;throttle check --share&lt;/code&gt; prints a sanitized summary you can post as a &lt;a href="https://github.com/KushagraKanaujia/throttle/issues/new?template=share-results.yml" rel="noopener noreferrer"&gt;results issue&lt;/a&gt;. I'm collecting what real serving changes actually do to cost, and I read every one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
