<?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: Andrey Altrouter</title>
    <description>The latest articles on DEV Community by Andrey Altrouter (@altrouter).</description>
    <link>https://dev.to/altrouter</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%2F4074301%2F0600ae16-ff26-459e-8ddd-ace73be1a5a1.png</url>
      <title>DEV Community: Andrey Altrouter</title>
      <link>https://dev.to/altrouter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/altrouter"/>
    <language>en</language>
    <item>
      <title>Prompt caching has a break-even point, and it's 22%</title>
      <dc:creator>Andrey Altrouter</dc:creator>
      <pubDate>Sun, 16 Aug 2026 08:46:58 +0000</pubDate>
      <link>https://dev.to/altrouter/prompt-caching-has-a-break-even-point-and-its-22-7d</link>
      <guid>https://dev.to/altrouter/prompt-caching-has-a-break-even-point-and-its-22-7d</guid>
      <description>&lt;p&gt;Every guide to cutting LLM costs eventually says the same thing: turn on prompt caching. Almost none of them mention that caching can make your bill &lt;strong&gt;larger&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It has a break-even point, it is computable, and most teams never check which side of it they're on.&lt;/p&gt;

&lt;p&gt;Two words first, because the whole argument lives in them. A &lt;strong&gt;token&lt;/strong&gt; is roughly ¾ of a word; models bill per million of them. &lt;strong&gt;Prompt caching&lt;/strong&gt; stores the front part of your prompt — the system prompt, the tool definitions, the documents you resend every time — so the model doesn't reprocess it on the next request. It matches on an exact prefix: change one byte anywhere near the start and everything after it is a miss.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache writes cost more than plain tokens
&lt;/h3&gt;

&lt;p&gt;Here is the part that gets skipped. Caching does not have one price, it has two, and one of them is a penalty.&lt;/p&gt;

&lt;p&gt;On Anthropic's API, relative to the normal input price per token:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Multiplier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal input token&lt;/td&gt;
&lt;td&gt;1.0×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache &lt;strong&gt;write&lt;/strong&gt;, 5-minute TTL&lt;/td&gt;
&lt;td&gt;1.25×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache &lt;strong&gt;write&lt;/strong&gt;, 1-hour TTL&lt;/td&gt;
&lt;td&gt;2.0×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache &lt;strong&gt;read&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;0.1×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;TTL&lt;/strong&gt; is time-to-live: how long the entry survives after it was last touched. Five minutes by default.&lt;/p&gt;

&lt;p&gt;So a cache hit is a 90% discount, and a cache miss is a 25% &lt;em&gt;surcharge&lt;/em&gt;. Every request that doesn't find a warm entry writes a new one and pays extra for the privilege. Caching is a bet: you're wagering that the entry you just paid 1.25× to create will be read at least a couple of times before it expires.&lt;/p&gt;

&lt;h3&gt;
  
  
  The break-even hit rate
&lt;/h3&gt;

&lt;p&gt;Your &lt;strong&gt;hit rate&lt;/strong&gt; is the share of cacheable tokens served from cache rather than written to it. Call it &lt;code&gt;h&lt;/code&gt;, the write multiplier &lt;code&gt;W&lt;/code&gt;, and the read multiplier &lt;code&gt;R&lt;/code&gt;. Caching pays off when the blended cost drops below plain input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(1 − h)·W + h·R  &amp;lt;  1
h  &amp;gt;  (W − 1) / (W − R)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plug the numbers in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5-minute cache:&lt;/strong&gt; (1.25 − 1) / (1.25 − 0.1) = &lt;strong&gt;21.7%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1-hour cache:&lt;/strong&gt; (2 − 1) / (2 − 0.1) = &lt;strong&gt;52.6%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below roughly a 22% hit rate, the five-minute cache is costing you money. The one-hour TTL doubles the write cost, so it needs more than half your requests to hit before it earns its keep — it exists for bursty traffic with gaps longer than five minutes, not as a default upgrade.&lt;/p&gt;

&lt;p&gt;Make it concrete. A support bot on &lt;code&gt;claude-sonnet-5&lt;/code&gt; ($2.00 per 1M input tokens at list price) with a 20K-token prefix and 200 requests a day. Uncached input: $8.00/day. At a 90% hit rate: $1.72/day. At a 15% hit rate — requests spread far enough apart that most entries expire unread — $8.62/day. Same code, same feature flag, a bill that moved 8% in the wrong direction.&lt;/p&gt;

&lt;p&gt;"But my traffic is steady" is a reasonable objection, and if it's true you're fine. The teams that get burned are the ones with low-volume production traffic, a per-user prefix that's never shared, or a nightly batch job spread thin across an hour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measure your actual hit rate
&lt;/h3&gt;

&lt;p&gt;Don't estimate it. Every response reports it. Run your real traffic, in its real order, through this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fresh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# your real requests, in real order
&lt;/span&gt;    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SYSTEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cache_control&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ephemeral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}],&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;
    &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_creation_input_tokens&lt;/span&gt;
    &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_read_input_tokens&lt;/span&gt;
    &lt;span class="n"&gt;fresh&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt;

&lt;span class="n"&gt;hit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;billed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.25&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fresh&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hit rate &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | billed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;billed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fresh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x uncached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;hit&lt;/code&gt; comes back at 0% across repeated requests with an identical prefix, something is silently invalidating it — a timestamp in the system prompt, a UUID, an unsorted &lt;code&gt;json.dumps&lt;/code&gt;, a tool list assembled in a different order. The cache key is the exact bytes.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;cache_creation_input_tokens&lt;/code&gt; is 0 too, your prefix is below the minimum cacheable length. That threshold is per-model and it is not monotonic across generations: 512 tokens on Claude Opus 5, 1024 on Opus 4.8 and Sonnet 5, 4096 on Opus 4.6 and Haiku 4.5. A 3K-token prompt caches on one and silently doesn't on the other, with no error either way.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this doesn't fix
&lt;/h3&gt;

&lt;p&gt;A good hit rate cuts the token count. It does nothing to the other multiplier — the price per token — and your bill is the product of both. That's where a gateway comes in: &lt;a href="https://altrouter.ai" rel="noopener noreferrer"&gt;altrouter.ai&lt;/a&gt; resells the same models at 10–25% below the vendors' own list prices (&lt;code&gt;claude-sonnet-5&lt;/code&gt; at $1.69 per 1M input against Anthropic's $2.00), through the OpenAI-compatible API, so switching is a &lt;code&gt;base_url&lt;/code&gt; change. Its honest gap on this exact topic: our usage records don't break out cache-read tokens yet, so the measurement above has to come from the provider's response body rather than our dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  The one number to take away
&lt;/h3&gt;

&lt;p&gt;Caching is not free money, it's a bet at fixed odds: &lt;strong&gt;22% hit rate on the five-minute cache, 53% on the one-hour one.&lt;/strong&gt; Print your hit rate before you argue about breakpoint placement. If it's under the line, the cheapest change you can make today is turning caching off.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>cost</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The cheap model is only cheap for half your tasks</title>
      <dc:creator>Andrey Altrouter</dc:creator>
      <pubDate>Sat, 15 Aug 2026 04:55:32 +0000</pubDate>
      <link>https://dev.to/altrouter/the-cheap-model-is-only-cheap-for-half-your-tasks-29ac</link>
      <guid>https://dev.to/altrouter/the-cheap-model-is-only-cheap-for-half-your-tasks-29ac</guid>
      <description>&lt;p&gt;Most of us pick a model the same way: read a leaderboard, pick the best one we can afford, ship it. Then the bill arrives and the "cheap" model turns out not to be the cheap one.&lt;/p&gt;

&lt;p&gt;The reason is that there is no such thing as a cheap model. There is only a model that is cheap &lt;strong&gt;for the shape of your traffic&lt;/strong&gt; — and the ranking reorders when the shape changes.&lt;/p&gt;

&lt;p&gt;Quick vocabulary, because the whole argument lives in two words. A &lt;strong&gt;token&lt;/strong&gt; is roughly ¾ of a word; models bill per million of them. &lt;strong&gt;Input tokens&lt;/strong&gt; are what you send (prompt, files, chat history); &lt;strong&gt;output tokens&lt;/strong&gt; are what the model writes back. They have different prices, and the gap between them is not the same for every model.&lt;/p&gt;

&lt;h3&gt;
  
  
  The number you don't have yet
&lt;/h3&gt;

&lt;p&gt;Every model's price is two numbers, and every vendor publishes the ratio between them without commenting on it. Here it is, list prices per 1M tokens, snapshot taken 12 Aug 2026:&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;Input $/1M&lt;/th&gt;
&lt;th&gt;Output $/1M&lt;/th&gt;
&lt;th&gt;Output is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gemini-3.1-flash-lite&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;1.50&lt;/td&gt;
&lt;td&gt;6× input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;grok-4.3&lt;/td&gt;
&lt;td&gt;1.25&lt;/td&gt;
&lt;td&gt;2.50&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2× input&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-haiku-4-5&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;5.00&lt;/td&gt;
&lt;td&gt;5× input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gemini-3.5-flash&lt;/td&gt;
&lt;td&gt;1.50&lt;/td&gt;
&lt;td&gt;9.00&lt;/td&gt;
&lt;td&gt;6× input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-sonnet-5&lt;/td&gt;
&lt;td&gt;2.00&lt;/td&gt;
&lt;td&gt;10.00&lt;/td&gt;
&lt;td&gt;5× input&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Look at row two. Grok 4.3 charges only twice as much for writing as for reading, where everyone else charges five or six times. That single number decides whether it is expensive or a bargain — and which one it is depends entirely on you.&lt;/p&gt;

&lt;p&gt;So measure your own ratio before you compare anything. Every OpenAI-compatible response already carries it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;msgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completion_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# add it up over a few hundred real requests, then:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tok_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tok_out&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tok_in&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;price_in&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tok_out&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;price_out&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_out&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# claude-haiku-4-5
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_out&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# grok-4.3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Same two models, opposite verdict
&lt;/h3&gt;

&lt;p&gt;Take Haiku 4.5 and Grok 4.3 and run them through two ordinary jobs, per 1,000 requests, at the list prices above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classification&lt;/strong&gt; — you send 4,000 tokens of document and get back one word (50 tokens). Almost all of the bill is reading.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;claude-haiku-4-5: &lt;code&gt;4M × $1.00 + 0.05M × $5.00&lt;/code&gt; = &lt;strong&gt;$4.25&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;grok-4.3: &lt;code&gt;4M × $1.25 + 0.05M × $2.50&lt;/code&gt; = &lt;strong&gt;$5.12&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Haiku wins by 17%. Now the same two models on &lt;strong&gt;code generation&lt;/strong&gt; — 1,500 tokens in, 2,500 tokens out. Now almost all of the bill is writing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;claude-haiku-4-5: &lt;code&gt;1.5M × $1.00 + 2.5M × $5.00&lt;/code&gt; = &lt;strong&gt;$14.00&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;grok-4.3: &lt;code&gt;1.5M × $1.25 + 2.5M × $2.50&lt;/code&gt; = &lt;strong&gt;$8.12&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grok wins by 42%. Nothing changed except the shape of the traffic. Any blog post that tells you which model is cheapest, without asking what your job looks like, is guessing.&lt;/p&gt;

&lt;h3&gt;
  
  
  When the upgrade is nearly free
&lt;/h3&gt;

&lt;p&gt;The same arithmetic works in the other direction, and this is the part that surprised me. Compare gemini-3.5-flash ($1.50 / $9.00) with claude-sonnet-5 ($2.00 / $10.00). On that RAG workload — 8,000 in, 700 out, per 1,000 requests — Flash costs $18.30 and Sonnet costs $23.00. You are one quarter away from a model in a completely different class, while the word "flash" in the name suggests you are saving a fortune.&lt;/p&gt;

&lt;p&gt;Then add the multiplier nobody puts in the spreadsheet: &lt;strong&gt;retries&lt;/strong&gt;. If the cheap model fails one call in five and you re-run those on the expensive one, you pay for the cheap attempt &lt;em&gt;and&lt;/em&gt; the expensive one. At a 20% failure rate that Flash job is really $18.30 + 20% × $23.00 = $22.90 — the discount is gone, and you also shipped worse latency.&lt;/p&gt;

&lt;p&gt;Prices below list change the same arithmetic without changing its shape. I work on &lt;a href="https://altrouter.ai" rel="noopener noreferrer"&gt;altrouter.ai&lt;/a&gt;, which bills the same vendor models under list — Claude Sonnet 5 at $8.50 per 1M output against the official $10.00, Grok 4.3 at $2.12 against $2.50 — so the crossover points move, but you still have to know your own ratio to find them. It also does not host embedding models, and no discount will rescue a model that keeps failing your task.&lt;/p&gt;

&lt;h3&gt;
  
  
  The actual decision order
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure &lt;code&gt;prompt_tokens&lt;/code&gt; / &lt;code&gt;completion_tokens&lt;/code&gt;&lt;/strong&gt; on a few hundred real requests. This takes ten minutes and everything else depends on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If input dominates (10:1 or more)&lt;/strong&gt;, rank candidates by input price only. Output price is noise; ignore the headline number everyone quotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If output dominates (below 2:1)&lt;/strong&gt;, rank by output price only — and specifically look for models with a low output-to-input multiple.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price the next tier up on your own mix&lt;/strong&gt; before assuming you can't afford it. If it lands under ~1.5× and it removes a retry, it is cheaper, not dearer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-run this per endpoint, not per app.&lt;/strong&gt; Your classifier and your code generator are different workloads and deserve different models.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What this doesn't solve
&lt;/h3&gt;

&lt;p&gt;This is arithmetic about price, not about quality. It will not tell you whether Grok 4.3 writes code you'd merge — only you can judge that, on your tasks. It ignores latency, rate limits, and prompt caching, which can each move the answer more than the price gap does. And the numbers are a snapshot from 12 Aug 2026; every one of them will be stale within a quarter, though the method won't be.&lt;/p&gt;

&lt;p&gt;Pick the model for the task, not for the app. And before you argue about which one is cheaper, go print your two usage numbers — the argument is usually already settled by them.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>cost</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Your LLM gateway takes a cut. Seventeen lines of Python tell you how big.</title>
      <dc:creator>Andrey Altrouter</dc:creator>
      <pubDate>Fri, 14 Aug 2026 05:18:57 +0000</pubDate>
      <link>https://dev.to/altrouter/your-llm-gateway-takes-a-cut-seventeen-lines-of-python-tell-you-how-big-45jc</link>
      <guid>https://dev.to/altrouter/your-llm-gateway-takes-a-cut-seventeen-lines-of-python-tell-you-how-big-45jc</guid>
      <description>&lt;p&gt;You wanted to try three models from three vendors, so you did the sensible thing: pointed one client at a gateway, put one key in the environment, and stopped thinking about it. A &lt;strong&gt;gateway&lt;/strong&gt; here is a service that speaks the OpenAI API and forwards your requests to Anthropic, Google, OpenAI, xAI and the rest, so switching models is a string change instead of a new SDK.&lt;/p&gt;

&lt;p&gt;What almost nobody checks after that: what the gateway charges for the exact same tokens the vendor would have sold you directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you actually buy from a gateway
&lt;/h3&gt;

&lt;p&gt;Three things, and they are worth very different amounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One key and one invoice.&lt;/strong&gt; Real, and boring. It saves you three signups and three billing pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing and fallback.&lt;/strong&gt; If a provider returns 529 or a region goes dark, the gateway retries elsewhere. Worth something on production traffic, nothing on a weekend project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A price per token.&lt;/strong&gt; This is the one that varies by an order of magnitude between services, and the one nobody puts in a comparison table — because there is no single "gateway price". There is a price per model, and a service can sit below vendor list on one model and far above it on another.&lt;/p&gt;

&lt;p&gt;Vocabulary, in case it is new: models are billed per &lt;strong&gt;million tokens&lt;/strong&gt; (a token is roughly ¾ of a word), input and output priced separately, with output typically 3–10× more expensive. The &lt;strong&gt;list price&lt;/strong&gt; is what the vendor publishes on its own pricing page. That list price is your baseline — a gateway is either below it, at it, or taking a markup on top.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seventeen lines that answer it
&lt;/h3&gt;

&lt;p&gt;Many gateways publish per-model pricing in their models endpoint. If yours does, this reads it and prices out &lt;em&gt;your&lt;/em&gt; token mix, not a benchmark's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;GATEWAY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.altrouter.ai/v1/models/public&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# your gateway's models endpoint
&lt;/span&gt;&lt;span class="n"&gt;LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;15.00&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;  &lt;span class="c1"&gt;# vendor list $/1M in, out
&lt;/span&gt;&lt;span class="n"&gt;MIX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# your monthly millions of tokens: input, output
&lt;/span&gt;
&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GATEWAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-check&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;inp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_per_1m_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_per_1m_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LIST&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;inp&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;li&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LIST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;mine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MIX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;inp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;MIX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
    &lt;span class="n"&gt;vendor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MIX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;li&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;MIX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; gateway $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mine&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;8.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  list $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;8.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mine&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;vendor&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run on 2026-08-14 against the endpoint in the snippet, it prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpt-5.6            gateway $  935.09  list $ 1100.00  -15.0%
claude-sonnet-5    gateway $  677.91  list $  800.00  -15.3%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your gateway does not publish prices in that endpoint — plenty don't — use the invoice method instead: take last month's charge, divide by the input and output tokens the gateway logged, and you have your real effective $/1M. That number is the only one that matters, and it is the one you compare to the vendor's page.&lt;/p&gt;

&lt;p&gt;The obvious objection: &lt;em&gt;the mix is made up&lt;/em&gt;. It is — replace &lt;code&gt;MIX&lt;/code&gt; with your own two numbers before you believe any of the output. The ratio between input and output tokens is workload-specific, and since output costs several times more, a chat workload and a document-summarizing workload rank gateways differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  The four things I'd check before switching
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Price per model, on your mix.&lt;/strong&gt; The script above. A gateway that is cheap on a small model can be expensive on the large one you actually run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whether &lt;code&gt;base_url&lt;/code&gt; is genuinely the only change.&lt;/strong&gt; Test streaming, tool calls, and the &lt;code&gt;usage&lt;/code&gt; object in the response. Those are where compatibility usually breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What happens on a provider outage.&lt;/strong&gt; Ask for the retry and fallback behaviour explicitly, then unplug a model and watch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your exit.&lt;/strong&gt; If leaving means rewriting anything beyond a URL and a key, that is not a gateway, that is a platform.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Disclosure, since the URL in the snippet is mine: I work on &lt;a href="https://altrouter.ai" rel="noopener noreferrer"&gt;altrouter.ai&lt;/a&gt;, which is why I could hardcode an endpoint that publishes its prices. It resells vendor models below list — Claude Sonnet 5 at $1.69 / $8.50 per 1M against the official $2.00 / $10.00, Opus 4.5 at $3.74 / $18.75 against $5.00 / $25.00, discounts running 10–25% by model, prices as of August 2026. Point the script at whatever you use now; the arithmetic does not care.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this does not tell you
&lt;/h3&gt;

&lt;p&gt;Price, and only price. The script says nothing about latency, uptime, rate limits, or whether prompt caching is passed through at the vendor's discount — check that separately, it can outweigh a 15% price gap. And the honest gaps on my side: no embedding models, no data residency options, no SLA of our own beyond the upstream vendor's. If you are on one vendor and never plan to leave, buy direct — you save exactly the middleman's margin.&lt;/p&gt;

&lt;p&gt;Run the seventeen lines on your own gateway this week. Whatever the number is, it is better to know it than to assume the convenience was free.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>python</category>
    </item>
    <item>
      <title>Your LLM bill has two levers. Your team only pulls one.</title>
      <dc:creator>Andrey Altrouter</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:19:53 +0000</pubDate>
      <link>https://dev.to/altrouter/your-llm-bill-has-two-levers-your-team-only-pulls-one-g95</link>
      <guid>https://dev.to/altrouter/your-llm-bill-has-two-levers-your-team-only-pulls-one-g95</guid>
      <description>&lt;p&gt;Every guide to cutting LLM costs is about the same thing: send fewer tokens. Trim the system prompt, cache the prefix, retrieve less, route easy requests to a small model. All of it works. And all of it is one half of the equation.&lt;/p&gt;

&lt;p&gt;Your bill is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bill = tokens × price_per_token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two factors. Multiplication. Every cost-cutting article I have read attacks the left one and treats the right one as a law of physics. It is not — it is a number on a pricing page, and pricing pages are not the only place those models are sold.&lt;/p&gt;

&lt;h3&gt;
  
  
  The two levers, in the same units
&lt;/h3&gt;

&lt;p&gt;A quick vocabulary check, because the whole argument lives in these words. A &lt;strong&gt;token&lt;/strong&gt; is roughly ¾ of a word — models are billed per million of them. &lt;strong&gt;Input tokens&lt;/strong&gt; are what you send (prompt, files, chat history), &lt;strong&gt;output tokens&lt;/strong&gt; are what the model writes back. Output costs 3–10× more per token, which is why it usually dominates the bill. &lt;strong&gt;Prompt caching&lt;/strong&gt; means the provider stores your unchanged prefix and re-reads it at a large discount, often around 10% of the input price — you pay a small premium the first time to write the cache, then read it cheaply.&lt;/p&gt;

&lt;p&gt;Now, one workload. A team runs a coding agent, and last month it burned &lt;strong&gt;200M input and 40M output tokens&lt;/strong&gt; on Claude Sonnet 5. At list price ($2.00 in / $10.00 out per 1M):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;200 × $2.00 + 40 × $10.00 = $400 + $400 = $800&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lever one — fewer tokens.&lt;/strong&gt; Say 70% of that input is a stable prefix (the same repo files, the same instructions) and you make it cacheable. That 140M drops to roughly $0.20 per 1M instead of $2.00. Input becomes &lt;code&gt;140 × $0.20 + 60 × $2.00 = $148&lt;/code&gt;. Output does not cache — it is generated fresh every time. New total: &lt;strong&gt;$548&lt;/strong&gt;, a 31% cut. That is a good month of engineering work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lever two — cheaper tokens.&lt;/strong&gt; Same tokens, same model, price reduced 15%. $800 becomes &lt;strong&gt;$680&lt;/strong&gt;. Zero engineering work.&lt;/p&gt;

&lt;p&gt;Neither is the interesting part. The interesting part is that they multiply:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Monthly bill&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List price, no caching&lt;/td&gt;
&lt;td&gt;$800.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching only&lt;/td&gt;
&lt;td&gt;$548.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cheaper price only&lt;/td&gt;
&lt;td&gt;$680.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Both&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$465.80&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pulling both levers is a 42% cut. Pulling the one everybody writes about is 31%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the second lever gets ignored
&lt;/h3&gt;

&lt;p&gt;Because it does not feel like engineering. Caching is a diff you can review, benchmark, and put in a changelog. "We pay less per token" is a procurement decision, so it falls between the team that owns the code and the team that owns the invoice, and nobody optimizes it.&lt;/p&gt;

&lt;p&gt;It is also the lever with no quality tradeoff. Every token-side optimization trades something: caching adds cache-invalidation bugs, retrieval trims context the model might have needed, routing to a smaller model risks a worse answer that costs more in retries. Changing the price per token changes exactly one thing — the price per token. The weights, the context window, and the output are identical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the price is actually negotiable
&lt;/h3&gt;

&lt;p&gt;Disclosure before the numbers: I work on &lt;a href="https://altrouter.ai" rel="noopener noreferrer"&gt;altrouter.ai&lt;/a&gt;, a gateway that resells the same vendor models below their list price — Claude Sonnet 5 at $1.69 / $8.50 per 1M against the official $2.00 / $10.00, Opus 4.5 at $3.74 / $18.75 against $5.00 / $25.00, GPT-5.6 at $2.13 / $12.75 against $2.50 / $15.00. Discounts run 10–25% depending on the model, the API is OpenAI-compatible, so switching is a &lt;code&gt;base_url&lt;/code&gt; change. Prices as of August 2026.&lt;/p&gt;

&lt;p&gt;The honest gaps, so you hear them from me and not from the comments: no embedding models, no data residency options, no SLA of our own beyond what the upstream vendor delivers, and no invoicing for legal entities yet. If any of those is a requirement, this lever is closed for you and lever one is all you have.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to do this week
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull last month's spend and split it into input, output, and cached input.&lt;/strong&gt; If you cannot produce that split, you cannot price anything — in/out prices differ by 3–10×, and cached input by another 10×.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiply your actual token counts by two or three candidate prices.&lt;/strong&gt; Not benchmark tokens — yours. The ratio is workload-specific.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do the caching work anyway.&lt;/strong&gt; The levers multiply; skipping one to take the other is leaving the smaller half on the table.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The point is not that one lever beats the other. It is that you are running an optimization with two variables and holding one constant for no reason other than habit.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>cost</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your model benchmark measures everything except the bill</title>
      <dc:creator>Andrey Altrouter</dc:creator>
      <pubDate>Wed, 12 Aug 2026 11:30:17 +0000</pubDate>
      <link>https://dev.to/altrouter/your-model-benchmark-measures-everything-except-the-bill-4i8o</link>
      <guid>https://dev.to/altrouter/your-model-benchmark-measures-everything-except-the-bill-4i8o</guid>
      <description>&lt;p&gt;Every model benchmark I read ranks the same two things: how good the output was, and sometimes how many tokens it took. Almost none of them print the number you actually get charged for.&lt;/p&gt;

&lt;p&gt;That gap matters, because the two rankings are not the same list. A model can win on quality, lose on tokens, and still be the cheapest way to finish your task — or the opposite. You cannot tell which without doing the multiplication yourself.&lt;/p&gt;

&lt;p&gt;Here is the multiplication.&lt;/p&gt;

&lt;h2&gt;
  
  
  The formula
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cost = (input_tokens / 1M) × price_in + (output_tokens / 1M) × price_out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the whole thing. Two numbers from the benchmark, two numbers from the vendor's pricing page. The reason it is worth writing down is that every term in it moves independently, and benchmarks only ever report the first two.&lt;/p&gt;

&lt;h2&gt;
  
  
  A worked example
&lt;/h2&gt;

&lt;p&gt;Take one coding task. Say it consumes &lt;strong&gt;40K input tokens and 12K output tokens&lt;/strong&gt; — the shape of a real agent run with a few files in context and a couple of iterations. These numbers are an assumption for the example, not a measurement; substitute your own from your logs.&lt;/p&gt;

&lt;p&gt;Vendor list prices per 1M tokens, as of August 2026:&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;in $&lt;/th&gt;
&lt;th&gt;out $&lt;/th&gt;
&lt;th&gt;Cost of one task&lt;/th&gt;
&lt;th&gt;100 tasks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.5&lt;/td&gt;
&lt;td&gt;5.00&lt;/td&gt;
&lt;td&gt;25.00&lt;/td&gt;
&lt;td&gt;$0.500&lt;/td&gt;
&lt;td&gt;$50.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.6&lt;/td&gt;
&lt;td&gt;2.50&lt;/td&gt;
&lt;td&gt;15.00&lt;/td&gt;
&lt;td&gt;$0.280&lt;/td&gt;
&lt;td&gt;$28.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 5&lt;/td&gt;
&lt;td&gt;2.00&lt;/td&gt;
&lt;td&gt;10.00&lt;/td&gt;
&lt;td&gt;$0.200&lt;/td&gt;
&lt;td&gt;$20.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok 4.5&lt;/td&gt;
&lt;td&gt;2.00&lt;/td&gt;
&lt;td&gt;6.00&lt;/td&gt;
&lt;td&gt;$0.152&lt;/td&gt;
&lt;td&gt;$15.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 4.5&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;5.00&lt;/td&gt;
&lt;td&gt;$0.100&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3 Flash&lt;/td&gt;
&lt;td&gt;0.50&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;$0.056&lt;/td&gt;
&lt;td&gt;$5.60&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nine times between the top and the bottom row. No leaderboard shows you that spread, because no leaderboard multiplies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap in the cheap column
&lt;/h2&gt;

&lt;p&gt;Now the part that makes the table dangerous if you read it naively.&lt;/p&gt;

&lt;p&gt;Token counts are not a property of the task. They are a property of the &lt;strong&gt;model on&lt;/strong&gt; that task. A weaker model that misunderstands the requirement, retries twice, re-reads the whole file and asks a clarifying question burns three or four times the tokens of a model that gets it in one pass.&lt;/p&gt;

&lt;p&gt;Run the arithmetic again. Haiku 4.5 is five times cheaper per token than Sonnet 5. If it needs four times the tokens to converge, one task costs $0.40 instead of $0.10 — and Sonnet, at $0.20, is now &lt;strong&gt;twice as cheap&lt;/strong&gt; as the "cheap" model.&lt;/p&gt;

&lt;p&gt;This is why "just use a smaller model" is advice, not a strategy. The only way to know is to log input and output tokens per task, per model, and multiply. Both numbers, separately: output usually dominates the bill, and it is the one that explodes when a model starts thinking out loud.&lt;/p&gt;

&lt;p&gt;Same reason time-to-finish deserves a column. A model that produces correct code after forty minutes of tool calls is not free just because each call is small.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Log tokens per task, split into input and output.&lt;/strong&gt; If your framework does not expose them, most gateways do. Without the split you cannot price anything, because in/out prices differ by 3–10×.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclude cache reads or price them separately.&lt;/strong&gt; Cached input is usually an order of magnitude cheaper; mixing it in makes your numbers look better than reality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price your top three candidates on your own tasks&lt;/strong&gt;, not on a public benchmark's tasks. The token ratio is workload-specific — long-context refactoring and short algorithmic prompts produce completely different bills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recompute quarterly.&lt;/strong&gt; Model prices move, and new models land every few weeks at a different point on the curve.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do this once and the model choice stops being a debate about vibes. It becomes a number with a currency symbol on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the price itself is negotiable
&lt;/h2&gt;

&lt;p&gt;One more term in that formula is worth attention, and it is the one everybody treats as fixed: &lt;code&gt;price_in&lt;/code&gt; and &lt;code&gt;price_out&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vendor list price is not the only price those models sell at. I work on &lt;a href="https://altrouter.ai" rel="noopener noreferrer"&gt;altrouter.ai&lt;/a&gt;, a gateway that resells the same models below the vendor's list — Claude Opus 4.5 at $3.74 / $18.75 per 1M against the official $5.00 / $25.00, Sonnet 5 at $1.69 / $8.50 against $2.00 / $10.00, and so on across 44 models on an OpenAI-compatible API. The discount is a standing price, shown next to the official one on every model page, not an intro offer.&lt;/p&gt;

&lt;p&gt;Plug it into the same example: the 100-task run on Opus 4.5 costs $37.44 instead of $50.00. Same weights, same tokens, same code — only the third and fourth term of the formula changed.&lt;/p&gt;

&lt;p&gt;I am obviously not a neutral party on that last paragraph, so treat it the way you should treat the rest of this post: as arithmetic you can check. The formula is public, the list prices are public, and your token counts are in your own logs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>programming</category>
      <category>cost</category>
    </item>
  </channel>
</rss>
