<?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: CloudGPU</title>
    <description>The latest articles on DEV Community by CloudGPU (@cloudgpu_app).</description>
    <link>https://dev.to/cloudgpu_app</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%2F4202377%2F0d175f44-703f-4bbe-9f65-e81aa5b0ae28.png</url>
      <title>DEV Community: CloudGPU</title>
      <link>https://dev.to/cloudgpu_app</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cloudgpu_app"/>
    <language>en</language>
    <item>
      <title>Use DeepSeek V4.1 Flash and Kimi in opencode via a custom OpenAI-compatible provider</title>
      <dc:creator>CloudGPU</dc:creator>
      <pubDate>Sun, 25 Oct 2026 22:22:44 +0000</pubDate>
      <link>https://dev.to/cloudgpu_app/use-deepseek-v41-flash-and-kimi-in-opencode-via-a-custom-openai-compatible-provider-5co4</link>
      <guid>https://dev.to/cloudgpu_app/use-deepseek-v41-flash-and-kimi-in-opencode-via-a-custom-openai-compatible-provider-5co4</guid>
      <description>&lt;p&gt;opencode ships with a long list of built-in providers, but you are not limited to them. Its docs describe a &lt;strong&gt;custom provider&lt;/strong&gt; path for any OpenAI-compatible endpoint: you declare the provider in &lt;code&gt;opencode.json&lt;/code&gt;, point it at a base URL, list the model IDs, and they show up in the model picker.&lt;/p&gt;

&lt;p&gt;This post walks through that setup with two models, &lt;strong&gt;DeepSeek V4.1 Flash&lt;/strong&gt; (&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;) and &lt;strong&gt;Kimi K3&lt;/strong&gt; (&lt;code&gt;kimi-k3&lt;/code&gt;), plus two extras in the same config: &lt;code&gt;kimi-k2.6&lt;/code&gt; and &lt;code&gt;glm-5.3-flash&lt;/code&gt;. The endpoint in the examples is CloudGPU's OpenAI-compatible API at &lt;code&gt;https://cloudgpu.app/v1&lt;/code&gt;, but the same steps apply to any provider that speaks &lt;code&gt;/v1/chat/completions&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What's tested and what isn't:&lt;/strong&gt; on 2026-10-26 we ran this setup end to end in opencode 1.19.4. The &lt;code&gt;opencode.json&lt;/code&gt; below loaded as written with no schema errors, &lt;code&gt;opencode models cloudgpu&lt;/code&gt; listed all four models, and &lt;code&gt;opencode run -m ...&lt;/code&gt; returned a reply from both &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt; and &lt;code&gt;kimi-k3&lt;/code&gt;. All four model IDs were also listed by &lt;code&gt;GET /v1/models&lt;/code&gt;, and a direct chat request to each one replied normally. Not yet verified: the interactive &lt;code&gt;/models&lt;/code&gt; screen in the TUI, the &lt;code&gt;/connect&lt;/code&gt; key flow, and how &lt;code&gt;limit.output&lt;/code&gt; maps onto requests. Those parts follow opencode's official docs, so read &lt;em&gt;"according to the docs"&lt;/em&gt; literally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;opencode installed (see the &lt;a href="https://opencode.ai/docs/" rel="noopener noreferrer"&gt;opencode docs&lt;/a&gt; for install options).&lt;/li&gt;
&lt;li&gt;An API key for your OpenAI-compatible endpoint. For CloudGPU, keys are created on the API page and look like &lt;code&gt;cgw-sk-...&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The exact model IDs your endpoint serves. Here: &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;, &lt;code&gt;kimi-k3&lt;/code&gt;, &lt;code&gt;kimi-k2.6&lt;/code&gt;, &lt;code&gt;glm-5.3-flash&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Export your key
&lt;/h2&gt;

&lt;p&gt;opencode's config supports &lt;code&gt;{env:VARIABLE_NAME}&lt;/code&gt; substitution (&lt;a href="https://opencode.ai/docs/config#env-vars" rel="noopener noreferrer"&gt;Config → Env vars&lt;/a&gt;), so the key never has to live in the JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CGW_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cgw-sk-..."&lt;/span&gt;   &lt;span class="c"&gt;# add to ~/.bashrc / ~/.zshrc to keep it across shells&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Add the provider to &lt;code&gt;opencode.json&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Create (or edit) &lt;code&gt;opencode.json&lt;/code&gt; in your project root. Per the docs, project config takes precedence over the global file at &lt;code&gt;~/.config/opencode/opencode.json&lt;/code&gt;, and config files are merged, so you can also put the &lt;code&gt;provider&lt;/code&gt; block in the global file if you want it in every project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://opencode.ai/config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cloudgpu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CloudGPU"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cloudgpu.app/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{env:CGW_API_KEY}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deepseek-v4.1-flash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DeepSeek V4.1 Flash"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"kimi-k3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimi K3"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"kimi-k2.6"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimi K2.6"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"glm-5.3-flash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GLM-5.3 Flash"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each field does, per opencode's Providers docs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cloudgpu&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The provider ID. You pick it; it becomes the first half of the model reference (&lt;code&gt;cloudgpu/&amp;lt;model&amp;gt;&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The AI SDK package. &lt;code&gt;@ai-sdk/openai-compatible&lt;/code&gt; is the one the docs name for OpenAI-compatible providers that use &lt;code&gt;/v1/chat/completions&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Display name in the UI.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;options.baseURL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The API endpoint. Note the &lt;code&gt;/v1&lt;/code&gt; at the end.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;options.apiKey&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional; set via &lt;code&gt;{env:...}&lt;/code&gt; syntax. If you would rather store the key with &lt;code&gt;/connect&lt;/code&gt; (see below), you can drop this line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;models&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The model IDs to expose. Each &lt;strong&gt;key&lt;/strong&gt; must match the ID the endpoint expects; &lt;code&gt;name&lt;/code&gt; is only the label.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only need the two headline models? Delete the &lt;code&gt;kimi-k2.6&lt;/code&gt; and &lt;code&gt;glm-5.3-flash&lt;/code&gt; entries; nothing else changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternative: store the key with &lt;code&gt;/connect&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The docs also describe a credential flow: run &lt;code&gt;/connect&lt;/code&gt; inside opencode, scroll to &lt;strong&gt;Other&lt;/strong&gt;, enter the provider ID (&lt;code&gt;cloudgpu&lt;/code&gt;, matching the key in &lt;code&gt;opencode.json&lt;/code&gt;), then paste your key. That stores the credential only; you still need the &lt;code&gt;provider&lt;/code&gt; block above. Use one approach or the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Pick the model
&lt;/h2&gt;

&lt;p&gt;Start opencode in the project and run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;According to the docs, your custom provider and its models appear in this selection list. Choose &lt;strong&gt;DeepSeek V4.1 Flash&lt;/strong&gt; or &lt;strong&gt;Kimi K3&lt;/strong&gt;. (In our test we checked the list from the command line, not this screen.)&lt;/p&gt;

&lt;p&gt;To check from the command line that opencode picked up the provider, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;opencode models cloudgpu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our test with opencode 1.19.4, this listed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cloudgpu/deepseek-v4.1-flash
cloudgpu/glm-5.3-flash
cloudgpu/kimi-k2.6
cloudgpu/kimi-k3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To choose a model from the command line instead, use &lt;code&gt;--model&lt;/code&gt; / &lt;code&gt;-m&lt;/code&gt; in &lt;code&gt;provider/model&lt;/code&gt; form. In our test, &lt;code&gt;-m cloudgpu/deepseek-v4.1-flash&lt;/code&gt; (the dot in the ID is fine) and &lt;code&gt;-m cloudgpu/kimi-k3&lt;/code&gt; both returned replies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;opencode &lt;span class="nt"&gt;-m&lt;/span&gt; cloudgpu/deepseek-v4.1-flash
opencode run &lt;span class="nt"&gt;-m&lt;/span&gt; cloudgpu/kimi-k3 &lt;span class="s2"&gt;"Explain what this repo's main entry point does"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also set a default in &lt;code&gt;opencode.json&lt;/code&gt; with the top-level &lt;code&gt;"model"&lt;/code&gt; key, using the same &lt;code&gt;provider_id/model_id&lt;/code&gt; form, for example &lt;code&gt;"model": "cloudgpu/deepseek-v4.1-flash"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one for what?
&lt;/h2&gt;

&lt;p&gt;I'm not putting benchmark numbers here; try both on your own repo. A practical split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/strong&gt;: a sensible default for everyday edits, explanations, and small refactors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;kimi-k3&lt;/code&gt;&lt;/strong&gt;: a reasoning model; switch to it with &lt;code&gt;/models&lt;/code&gt; for multi-step changes or a second opinion on the same task. It spends output tokens on reasoning before it answers (see troubleshooting #4).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;kimi-k2.6&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;glm-5.3-flash&lt;/code&gt;&lt;/strong&gt;: already in the config, so comparing is one &lt;code&gt;/models&lt;/code&gt; switch away.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;This section is based on a real question we answered: someone added a DeepSeek model as a custom provider in a coding agent, entered the endpoint, key, and two models, and &lt;strong&gt;the model never showed up in the picker&lt;/strong&gt;. The model ID they had entered was a short alias, not the exact ID the endpoint lists. We can't say for sure that was the cause in their case, but a short alias like that is a common cause, and the same checklist applies to opencode.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The model doesn't appear in &lt;code&gt;/models&lt;/code&gt; (or requests fail with "model not found")
&lt;/h3&gt;

&lt;p&gt;The keys under &lt;code&gt;models&lt;/code&gt; must match, character for character, the IDs your endpoint returns from &lt;code&gt;GET /v1/models&lt;/code&gt;. Check them directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://cloudgpu.app/v1/models &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$CGW_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;code&gt;id&lt;/code&gt; values from the response into &lt;code&gt;opencode.json&lt;/code&gt;. Common mismatches: a short alias (&lt;code&gt;deepseek-flash&lt;/code&gt;), a missing version segment (&lt;code&gt;deepseek-v4-flash&lt;/code&gt; vs &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;), or different capitalization.&lt;/p&gt;

&lt;p&gt;Also confirm the provider ID matches everywhere: the key under &lt;code&gt;provider&lt;/code&gt;, the ID you typed in &lt;code&gt;/connect&lt;/code&gt; (if you used it), and the prefix in &lt;code&gt;-m cloudgpu/...&lt;/code&gt;. opencode's own troubleshooting list calls out the &lt;code&gt;/connect&lt;/code&gt; ID mismatch, and &lt;code&gt;opencode auth list&lt;/code&gt; shows which credentials are stored.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The base URL is missing &lt;code&gt;/v1&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@ai-sdk/openai-compatible&lt;/code&gt; appends paths like &lt;code&gt;/chat/completions&lt;/code&gt; to &lt;code&gt;baseURL&lt;/code&gt;. Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://cloudgpu.app/v1      ✅
https://cloudgpu.app         ❌
https://cloudgpu.app/v1/chat/completions   ❌ (too specific)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The environment variable isn't exported
&lt;/h3&gt;

&lt;p&gt;The docs note that if a variable referenced with &lt;code&gt;{env:...}&lt;/code&gt; is not set, it is replaced with an &lt;strong&gt;empty string&lt;/strong&gt;, so no key is sent and the request is rejected. In our test (opencode 1.19.4, &lt;code&gt;CGW_API_KEY&lt;/code&gt; empty) the error was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Provide an Authorization: Bearer &amp;lt;api_key&amp;gt; header.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the variable in the same shell you launch opencode from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CGW_API_KEY&lt;/span&gt;:+set&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;   &lt;span class="c"&gt;# prints "set" if the variable is present&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you set it in &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.bashrc&lt;/code&gt;, open a new terminal (or &lt;code&gt;source&lt;/code&gt; the file) before starting opencode. Desktop launchers and IDE terminals may not read your shell profile.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Empty replies from reasoning models
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;kimi-k3&lt;/code&gt;, &lt;code&gt;kimi-k2.6&lt;/code&gt;, and &lt;code&gt;glm-5.3-flash&lt;/code&gt; reason before they answer, and the reasoning counts against the output limit. In our 2026-10-26 test against the API directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;with &lt;code&gt;max_tokens: 20&lt;/code&gt;, all three returned &lt;strong&gt;empty or &lt;code&gt;null&lt;/code&gt; content&lt;/strong&gt;, because reasoning used up the tokens first;&lt;/li&gt;
&lt;li&gt;with &lt;code&gt;max_tokens: 800&lt;/code&gt;, all three replied normally;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kimi-k3&lt;/code&gt; used &lt;strong&gt;1027 completion tokens&lt;/strong&gt; to answer "ok".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If the reply is empty, raise &lt;code&gt;max_tokens&lt;/code&gt; or leave it unset.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In opencode, the per-model knob the docs describe for custom providers is the optional &lt;code&gt;limit&lt;/code&gt; block (&lt;code&gt;limit.context&lt;/code&gt;, &lt;code&gt;limit.output&lt;/code&gt;). If you set &lt;code&gt;limit.output&lt;/code&gt; low, or a tool or agent config passes a small output cap, you may hit the same empty-reply behavior. If you add &lt;code&gt;limit&lt;/code&gt;, use real values from your provider's model docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"kimi-k3": {
  "name": "Kimi K3",
  "limit": { "context": &amp;lt;context tokens&amp;gt;, "output": &amp;lt;max output tokens&amp;gt; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Replace the placeholders with numbers; the snippet is not valid JSON as written.) How opencode maps &lt;code&gt;limit.output&lt;/code&gt; onto the request is per its docs; I haven't verified it against these models inside opencode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Billing
&lt;/h2&gt;

&lt;p&gt;CloudGPU's API runs on a prepaid balance (card, Alipay, Google Pay, Apple Pay, or USDT). The model list and API key setup are on the &lt;a href="https://cloudgpu.app/api?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=202611_seg04_codingagent&amp;amp;utm_content=devto_opencode_custom_provider" rel="noopener noreferrer"&gt;CloudGPU API page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;export CGW_API_KEY=...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;provider&lt;/code&gt; block with &lt;code&gt;"npm": "@ai-sdk/openai-compatible"&lt;/code&gt;, &lt;code&gt;"baseURL": "https://cloudgpu.app/v1"&lt;/code&gt;, and &lt;code&gt;"apiKey": "{env:CGW_API_KEY}"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;List exact model IDs under &lt;code&gt;models&lt;/code&gt;, verified against &lt;code&gt;GET /v1/models&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;opencode models cloudgpu&lt;/code&gt; to confirm the models are listed, then pick &lt;code&gt;cloudgpu/deepseek-v4.1-flash&lt;/code&gt; or &lt;code&gt;cloudgpu/kimi-k3&lt;/code&gt; with &lt;code&gt;/models&lt;/code&gt; or &lt;code&gt;-m&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Empty reply from a reasoning model? Raise &lt;code&gt;max_tokens&lt;/code&gt; or leave it unset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Docs used: &lt;a href="https://opencode.ai/docs/providers#custom" rel="noopener noreferrer"&gt;opencode Providers → Custom provider&lt;/a&gt;, &lt;a href="https://opencode.ai/docs/config#env-vars" rel="noopener noreferrer"&gt;opencode Config → Env vars&lt;/a&gt;, &lt;a href="https://opencode.ai/docs/models" rel="noopener noreferrer"&gt;opencode Models&lt;/a&gt;, &lt;a href="https://opencode.ai/docs/cli" rel="noopener noreferrer"&gt;opencode CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I work on CloudGPU.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opencode</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Self-Host an LLM on a Rented GPU or Pay per Token? A Break-Even Calculator (2026)</title>
      <dc:creator>CloudGPU</dc:creator>
      <pubDate>Sun, 25 Oct 2026 13:08:44 +0000</pubDate>
      <link>https://dev.to/cloudgpu_app/self-host-an-llm-on-a-rented-gpu-or-pay-per-token-a-break-even-calculator-2026-1336</link>
      <guid>https://dev.to/cloudgpu_app/self-host-an-llm-on-a-rented-gpu-or-pay-per-token-a-break-even-calculator-2026-1336</guid>
      <description>&lt;p&gt;&lt;strong&gt;Self-hosting on a rented GPU is cheaper than a per-token API only when you keep the GPU busy: the break-even is the hourly GPU price divided by the APIâ€™s price per token, expressed as tokens you must actually generate and process every hour.&lt;/strong&gt; Below that throughput the API wins; above it the GPU wins. This post gives the formula, a worked example with an open 32B model on a single 32 GB card, and a script to run with your own measurements.&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;api_cost_per_hour  = (input_tokens_per_hour Ã— input_price + output_tokens_per_hour Ã— output_price) / 1,000,000
gpu_cost_per_hour  = hourly_gpu_price                     # you pay it whether the GPU is busy or idle

break_even_tokens_per_hour = hourly_gpu_price / blended_price_per_token
blended_price_per_token    = (r Ã— input_price + output_price) / ((r + 1) Ã— 1,000,000)    # r = input:output ratio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then correct for &lt;strong&gt;utilisation&lt;/strong&gt;: if your GPU is busy only 40% of the hours you rent it, the throughput you need while busy is break-even Ã· 0.4.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: Qwen3 32B (4-bit) on an RTX 5090 32G
&lt;/h2&gt;

&lt;p&gt;Qwen3 32B is an open-weight model (Apache-2.0) that is not offered on the CloudGPU API, so self-hosting is the way to run it here. We use the 4-bit AWQ build because it fits a 32 GB card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model size (estimate).&lt;/strong&gt; Hugging Face metadata for &lt;code&gt;Qwen/Qwen3-32B&lt;/code&gt; lists 32,762,123,264 parameters. In &lt;code&gt;Qwen/Qwen3-32B-AWQ&lt;/code&gt;, 31.21B of them are stored at 4 bits and 1.56B stay in BF16:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;31.21B Ã— 0.5 byte           â‰ˆ 15.6 GB   (4-bit weights)
 1.56B Ã— 2 bytes            â‰ˆ  3.1 GB   (BF16 embeddings, norms, output layer)
AWQ scales/zeros, group 128 â‰ˆ  0.6 GB
total                       â‰ˆ 19.3 GB   (the repository's files add up to 19.33 GB)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The FP8 build (&lt;code&gt;Qwen/Qwen3-32B-FP8&lt;/code&gt;, about 34.3 GB of files) does not fit in 32 GB of VRAM; it needs a 48 GB card such as the RTX 4090 48G. Figures read from the Hugging Face API on 2026-10-23 21:12 Beijing time; see also &lt;a href="https://cloudgpu.app/run/qwen3-32b" rel="noopener noreferrer"&gt;Qwen3 32B VRAM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context headroom (estimate).&lt;/strong&gt; With an FP16 KV cache, Qwen3 32B stores 2 Ã— 64 layers Ã— 8 KV heads Ã— 128 Ã— 2 bytes = 262,144 bytes (about 0.26 MB) per token: about 2.1 GB at 8k tokens and 8.6 GB at 32k. After about 19.3 GB of weights, a 32 GB card has roughly 12.7 GB for the KV cache and runtime overhead, so at most about 48k cached tokens shared by all concurrent requests, fewer once the overhead is counted.&lt;/p&gt;

&lt;p&gt;Inputs (2026-10-23 21:13 Beijing time):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090 32G list price&lt;/td&gt;
&lt;td&gt;$0.59 per hour, billed per minute&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cloudgpu.app/gpu-prices.json" rel="noopener noreferrer"&gt;https://cloudgpu.app/gpu-prices.json&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-token reference prices on the same balance&lt;/td&gt;
&lt;td&gt;glm-5.3-flash $0.16 in / $0.55 out; gpt-oss-120b $0.135 / $0.54; deepseek-v4-flash $0.27 / $1.08 (per 1M tokens)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cloudgpu.app/api" rel="noopener noreferrer"&gt;/api&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What a self-hosted token costs.&lt;/strong&gt; At a fixed $0.59 per hour, the cost per million tokens depends only on the throughput you sustain. The throughputs below are inputs to the arithmetic, not measurements:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sustained throughput (all requests, input + output)&lt;/th&gt;
&lt;th&gt;Tokens per hour&lt;/th&gt;
&lt;th&gt;Cost per 1M tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100 tokens/s&lt;/td&gt;
&lt;td&gt;0.36M&lt;/td&gt;
&lt;td&gt;â‰ˆ $1.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;250 tokens/s&lt;/td&gt;
&lt;td&gt;0.90M&lt;/td&gt;
&lt;td&gt;â‰ˆ $0.66&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 tokens/s&lt;/td&gt;
&lt;td&gt;1.80M&lt;/td&gt;
&lt;td&gt;â‰ˆ $0.33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000 tokens/s&lt;/td&gt;
&lt;td&gt;3.60M&lt;/td&gt;
&lt;td&gt;â‰ˆ $0.16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Break-even against per-token prices&lt;/strong&gt; (3 input : 1 output):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Per-token reference&lt;/th&gt;
&lt;th&gt;Blended price&lt;/th&gt;
&lt;th&gt;Break-even per hour&lt;/th&gt;
&lt;th&gt;Throughput needed at 100% / 50% utilisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;glm-5.3-flash&lt;/td&gt;
&lt;td&gt;$0.2575 / 1M&lt;/td&gt;
&lt;td&gt;â‰ˆ 2.29M tokens/h&lt;/td&gt;
&lt;td&gt;â‰ˆ 636 / 1,273 tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gpt-oss-120b&lt;/td&gt;
&lt;td&gt;$0.236 / 1M&lt;/td&gt;
&lt;td&gt;â‰ˆ 2.50M tokens/h&lt;/td&gt;
&lt;td&gt;â‰ˆ 694 / 1,387 tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deepseek-v4-flash&lt;/td&gt;
&lt;td&gt;$0.4725 / 1M&lt;/td&gt;
&lt;td&gt;â‰ˆ 1.25M tokens/h&lt;/td&gt;
&lt;td&gt;â‰ˆ 347 / 694 tokens/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are different models from Qwen3 32B, so the table compares cost only: decide on quality first, then use the arithmetic. How to read it: on one card you would need to sustain several hundred tokens per second, aggregated across concurrent requests, for every hour you pay for. That needs batching and steady traffic, and you should verify it with a benchmark on the card. For spiky or low-volume traffic, a per-token API is usually the lower-cost choice.&lt;/p&gt;

&lt;p&gt;We do not publish a measured tokens-per-second figure for this card here; measure your own with your prompt lengths and concurrency.&lt;/p&gt;

&lt;h2&gt;
  
  
  When renting the GPU wins anyway
&lt;/h2&gt;

&lt;p&gt;Price per token is not the only reason to rent:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Why a GPU makes sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The model is not offered as an API (e.g. Qwen3 32B on CloudGPU, a community fine-tune, your own LoRA)&lt;/td&gt;
&lt;td&gt;There is no per-token option to compare against&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large batch jobs with steady load (offline eval, synthetic data, embeddings, transcription batches)&lt;/td&gt;
&lt;td&gt;Utilisation is high and the batch finishes; destroy the instance afterwards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need custom serving: LoRA adapters, constrained decoding, specific quantisation&lt;/td&gt;
&lt;td&gt;You control the stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need image pipelines with custom nodes (ComfyUI)&lt;/td&gt;
&lt;td&gt;APIs expose fixed models only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When the API wins
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Traffic is spiky or low&lt;/td&gt;
&lt;td&gt;You would pay for idle GPU hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The model is too large for one rented card (e.g. DeepSeek V4, Kimi K3)&lt;/td&gt;
&lt;td&gt;Self-hosting would need far more VRAM than one card has&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need the model now, without ops work&lt;/td&gt;
&lt;td&gt;No boot, no downloads, no monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need a closed frontier model&lt;/td&gt;
&lt;td&gt;Only available as an API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For that last case, the same CloudGPU balance pays for the API. Our per-1M-token rate for each Claude model is shown next to the official list price on the &lt;a href="https://cloudgpu.app/api" rel="noopener noreferrer"&gt;API page&lt;/a&gt;; official list prices were checked 2026-10-24 on the official Claude pricing page and can change after that date. Rates for the other models are on the same page.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an always-on GPU costs
&lt;/h2&gt;

&lt;p&gt;If you keep a card running 24/7 to serve traffic, the bill is fixed regardless of tokens (list prices, 2026-10-23 21:13 Beijing time):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Card&lt;/th&gt;
&lt;th&gt;Per day (24 h)&lt;/th&gt;
&lt;th&gt;Per 30 days&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090 24G ($0.33/h)&lt;/td&gt;
&lt;td&gt;$7.92&lt;/td&gt;
&lt;td&gt;$237.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090 32G ($0.59/h)&lt;/td&gt;
&lt;td&gt;$14.16&lt;/td&gt;
&lt;td&gt;$424.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090 48G ($0.65/h)&lt;/td&gt;
&lt;td&gt;$15.60&lt;/td&gt;
&lt;td&gt;$468.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A800 80G ($1.09/h)&lt;/td&gt;
&lt;td&gt;$26.16&lt;/td&gt;
&lt;td&gt;$784.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A100 80G ($1.49/h)&lt;/td&gt;
&lt;td&gt;$35.76&lt;/td&gt;
&lt;td&gt;$1,072.80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;â€œFixed costâ€ does not mean unlimited output: the cardâ€™s throughput caps how many tokens you can serve. Also budget for restarts â€” destroying an instance deletes its disk, so a redeploy re-downloads weights. Stock changes during the day; check &lt;a href="https://cloudgpu.app/deploy" rel="noopener noreferrer"&gt;Deploy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A script for your own numbers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpu_price_h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_price_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_price_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_out_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;utilisation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;blended&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_out_ratio&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;in_price_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;out_price_m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_out_ratio&lt;/span&gt; &lt;span class="o"&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="mf"&gt;1e6&lt;/span&gt;   &lt;span class="c1"&gt;# $ per token
&lt;/span&gt;    &lt;span class="n"&gt;tokens_per_hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gpu_price_h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;blended&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tokens_per_hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens_per_hour&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;utilisation&lt;/span&gt;                       &lt;span class="c1"&gt;# tokens/h, tokens/s while busy
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpu_price_h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hours_per_day&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&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;gpu_price_h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hours_per_day&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cost_per_million&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpu_price_h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens_per_second&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;gpu_price_h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens_per_second&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                              &lt;span class="c1"&gt;# $ per 1M tokens
&lt;/span&gt;
&lt;span class="c1"&gt;# Qwen3 32B AWQ on an RTX 5090 32G at $0.59/h vs a $0.16 in / $0.55 out per-token reference (2026-10-23 21:13)
&lt;/span&gt;&lt;span class="n"&gt;tph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;break_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_out_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;utilisation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&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;break-even: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tph&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1e6&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;M tokens/h, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tps&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="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tokens/s while busy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&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;self-hosted cost at 500 tokens/s: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cost_per_million&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&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; per 1M tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&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;always-on RTX 5090 32G for 30 days: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.59&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="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;Replace the prices with the live values from &lt;a href="https://cloudgpu.app/pricing" rel="noopener noreferrer"&gt;/pricing&lt;/a&gt; and &lt;a href="https://cloudgpu.app/api" rel="noopener noreferrer"&gt;/api&lt;/a&gt; on the day you decide, and replace utilisation and the input:output ratio with your logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is self-hosting an LLM cheaper than using an API?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only if you keep the GPU busy enough. Divide the GPUâ€™s hourly price by the APIâ€™s blended price per token; if your measured sustained throughput is above that number, self-hosting is cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I calculate the break-even between GPU rental and API pricing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;break-even tokens per hour = hourly GPU price Ã· blended API price per token, where the blended price weights input and output by your traffic ratio. Divide by utilisation to get the throughput you need while busy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What utilisation do I need for self-hosting to pay off?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It depends on the model and card; compute break-even from the formula, then compare with the throughput you measure under realistic concurrency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why rent a GPU if the API is cheaper per token?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For models with no API, fine-tunes and LoRA adapters, custom serving stacks, ComfyUI pipelines, or steady batch jobs that keep the card busy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use the same balance for GPUs and the API?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. One prepaid balance covers per-minute GPU rental and per-token API calls.&lt;/p&gt;




&lt;p&gt;If you want to check the hourly side of the formula, the &lt;a href="https://cloudgpu.app/gpu-rental-per-minute-billing" rel="noopener noreferrer"&gt;per-minute GPU rental page&lt;/a&gt; explains how a job is billed. &lt;em&gt;Originally published at &lt;a href="https://cloudgpu.app/blog/self-host-llm-vs-api-break-even-2026" rel="noopener noreferrer"&gt;cloudgpu.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Break-even figures are arithmetic on list prices, not performance measurements. Prices were read on 2026-10-23 21:13 Beijing time (UTC+8); model sizes are estimates from Hugging Face metadata read at 21:12; current prices on &lt;a href="https://cloudgpu.app/deploy" rel="noopener noreferrer"&gt;/deploy&lt;/a&gt; and &lt;a href="https://cloudgpu.app/api" rel="noopener noreferrer"&gt;/api&lt;/a&gt; take precedence.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>llm</category>
      <category>selfhosted</category>
      <category>ai</category>
      <category>gpu</category>
    </item>
    <item>
      <title>KV Cache VRAM Calculator: How Much Memory Does Context Length Need? (2026)</title>
      <dc:creator>CloudGPU</dc:creator>
      <pubDate>Sat, 24 Oct 2026 13:07:30 +0000</pubDate>
      <link>https://dev.to/cloudgpu_app/kv-cache-vram-calculator-how-much-memory-does-context-length-need-2026-gc3</link>
      <guid>https://dev.to/cloudgpu_app/kv-cache-vram-calculator-how-much-memory-does-context-length-need-2026-gc3</guid>
      <description>&lt;p&gt;&lt;strong&gt;The KV cache is the memory a transformer uses to remember every token in the context, and its size grows linearly with context length:&lt;/strong&gt; bytes per token = 2 × layers × KV heads × head dimension × bytes per value. For Qwen3 32B at FP16 that is 256 KiB per token, or about 8 GB for a 32k-token context, on top of the model weights. This is why a model that loads fine can still run out of memory when you raise the context.&lt;/p&gt;

&lt;p&gt;This post gives the formula, the per-token numbers for popular open models (read from their &lt;code&gt;config.json&lt;/code&gt;), and how much context fits on 24, 32, 48 and 80 GB cards.&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;kv_bytes_per_token = 2 × num_hidden_layers × num_key_value_heads × head_dim × bytes_per_value
kv_total_bytes     = kv_bytes_per_token × context_tokens × concurrent_sequences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;2&lt;/strong&gt; is for keys and values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;num_key_value_heads&lt;/code&gt; is smaller than the number of attention heads in models with grouped-query attention (GQA), which is why modern models have much smaller caches than older ones.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bytes_per_value&lt;/code&gt; is 2 for FP16/BF16, 1 for 8-bit KV cache, about 0.5 for 4-bit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent sequences multiply the cache.&lt;/strong&gt; If your server keeps four parallel slots, budget four times the context.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Per-token KV cache for popular models (FP16)
&lt;/h2&gt;

&lt;p&gt;Architecture values are from each model’s &lt;code&gt;config.json&lt;/code&gt; on Hugging Face (read 2026-10-23). GB here means GiB (1024³ bytes).&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;Layers&lt;/th&gt;
&lt;th&gt;KV heads&lt;/th&gt;
&lt;th&gt;head_dim&lt;/th&gt;
&lt;th&gt;KV per token&lt;/th&gt;
&lt;th&gt;8k ctx&lt;/th&gt;
&lt;th&gt;32k ctx&lt;/th&gt;
&lt;th&gt;128k ctx&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Llama 3.1 8B&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;128 KiB&lt;/td&gt;
&lt;td&gt;1.0 GB&lt;/td&gt;
&lt;td&gt;4.0 GB&lt;/td&gt;
&lt;td&gt;16 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3 8B&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;144 KiB&lt;/td&gt;
&lt;td&gt;1.1 GB&lt;/td&gt;
&lt;td&gt;4.5 GB&lt;/td&gt;
&lt;td&gt;18 GB*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3 14B&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;160 KiB&lt;/td&gt;
&lt;td&gt;1.25 GB&lt;/td&gt;
&lt;td&gt;5.0 GB&lt;/td&gt;
&lt;td&gt;20 GB*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral Small 3 24B&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;160 KiB&lt;/td&gt;
&lt;td&gt;1.25 GB&lt;/td&gt;
&lt;td&gt;5.0 GB&lt;/td&gt;
&lt;td&gt;— (32k max)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3 32B&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;256 KiB&lt;/td&gt;
&lt;td&gt;2.0 GB&lt;/td&gt;
&lt;td&gt;8.0 GB&lt;/td&gt;
&lt;td&gt;32 GB*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Llama 3.3 70B&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;320 KiB&lt;/td&gt;
&lt;td&gt;2.5 GB&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;td&gt;40 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen2.5 72B&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;320 KiB&lt;/td&gt;
&lt;td&gt;2.5 GB&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;td&gt;40 GB*&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Beyond the model’s native window. Qwen3 dense models are documented with a native 32,768-token context, extendable with YaRN rope scaling; check the model card before going past the native length.&lt;/p&gt;

&lt;p&gt;The formula does not apply as-is to models with sliding-window layers (for example Gemma 3 and gpt-oss) or latent attention (DeepSeek V3-style MLA); their caches are smaller than this formula suggests.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much context fits on each card
&lt;/h2&gt;

&lt;p&gt;Total memory ≈ weights + KV cache + overhead. Weights are the Q4_K_M sizes on our &lt;a href="https://cloudgpu.app/run" rel="noopener noreferrer"&gt;/run&lt;/a&gt; pages; overhead is an &lt;strong&gt;assumed 1.5 GB&lt;/strong&gt; for CUDA context, buffers and the runtime. The result is a ceiling for a single sequence; runtimes reserve extra buffers, so plan below it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Qwen3 32B at Q4_K_M (≈ 19.5 GB weights, 256 KiB/token):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Card class&lt;/th&gt;
&lt;th&gt;Left for KV after weights + 1.5 GB&lt;/th&gt;
&lt;th&gt;Context ceiling (1 sequence)&lt;/th&gt;
&lt;th&gt;Practical guidance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;24 GB (RTX 4090 / 3090)&lt;/td&gt;
&lt;td&gt;≈ 3 GB&lt;/td&gt;
&lt;td&gt;≈ 12k tokens&lt;/td&gt;
&lt;td&gt;about 8k; tight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32 GB (RTX 5090)&lt;/td&gt;
&lt;td&gt;≈ 11 GB&lt;/td&gt;
&lt;td&gt;≈ 45k (native max 32k)&lt;/td&gt;
&lt;td&gt;16k–32k comfortable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;48 GB (RTX 4090 48G)&lt;/td&gt;
&lt;td&gt;≈ 27 GB&lt;/td&gt;
&lt;td&gt;≈ 110k&lt;/td&gt;
&lt;td&gt;full native 32k, or several parallel slots&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Llama 3.3 70B at Q4_K_M (≈ 41.5 GB weights, 320 KiB/token):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Card class&lt;/th&gt;
&lt;th&gt;Left for KV&lt;/th&gt;
&lt;th&gt;Context ceiling (1 sequence)&lt;/th&gt;
&lt;th&gt;Practical guidance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;48 GB (RTX 4090 48G / A6000)&lt;/td&gt;
&lt;td&gt;≈ 5 GB&lt;/td&gt;
&lt;td&gt;≈ 16k&lt;/td&gt;
&lt;td&gt;about 8k; tight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80 GB (A100 / A800)&lt;/td&gt;
&lt;td&gt;≈ 37 GB&lt;/td&gt;
&lt;td&gt;≈ 121k&lt;/td&gt;
&lt;td&gt;32k comfortable, with room for parallel requests&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The “practical guidance” column matches the per-model notes on our &lt;a href="https://cloudgpu.app/run/qwen3-32b" rel="noopener noreferrer"&gt;Qwen3 32B page&lt;/a&gt; and &lt;a href="https://cloudgpu.app/run/llama-3-3-70b" rel="noopener noreferrer"&gt;Llama 3.3 70B page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small calculator
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kv_gb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_per_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;layers&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;kv_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;bytes_per_value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;seqs&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;max_ctx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vram_gb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weights_gb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;bytes_per_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overhead_gb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vram_gb&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;weights_gb&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;overhead_gb&lt;/span&gt;
    &lt;span class="n"&gt;per_tok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;layers&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;kv_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;bytes_per_value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&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="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;per_tok&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;seqs&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="c1"&gt;# Qwen3 32B (64 layers, 8 KV heads, head_dim 128), Q4 weights ≈ 19.5 GB
&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;kv_gb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32768&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;          &lt;span class="c1"&gt;# 8.0
&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;max_ctx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;19.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;     &lt;span class="c1"&gt;# ≈ 45k (native limit is 32k)
&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;max_ctx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;19.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes_per_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# 8-bit KV: ≈ 24k
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read &lt;code&gt;num_hidden_layers&lt;/code&gt;, &lt;code&gt;num_key_value_heads&lt;/code&gt; and &lt;code&gt;head_dim&lt;/code&gt; (or &lt;code&gt;hidden_size / num_attention_heads&lt;/code&gt;) from the model’s &lt;code&gt;config.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to fit more context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Quantise the KV cache.&lt;/strong&gt; Halving bytes per value halves the cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ollama: 8-bit KV cache (requires flash attention)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_FLASH_ATTENTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OLLAMA_KV_CACHE_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;q8_0
ollama serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# vLLM: FP8 KV cache&lt;/span&gt;
vllm serve Qwen/Qwen3-32B-AWQ &lt;span class="nt"&gt;--kv-cache-dtype&lt;/span&gt; fp8 &lt;span class="nt"&gt;--max-model-len&lt;/span&gt; 32768
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quality impact is usually small at 8-bit and more noticeable at 4-bit; test on your own prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Set the context you need, not the maximum.&lt;/strong&gt; In Ollama, pass &lt;code&gt;"options": {"num_ctx": 16384}&lt;/code&gt; per request (or set &lt;code&gt;OLLAMA_CONTEXT_LENGTH&lt;/code&gt;). In vLLM, &lt;code&gt;--max-model-len&lt;/code&gt; caps the context and &lt;code&gt;--gpu-memory-utilization&lt;/code&gt; sets how much VRAM the cache may take.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Watch parallelism.&lt;/strong&gt; Ollama’s &lt;code&gt;OLLAMA_NUM_PARALLEL&lt;/code&gt; and vLLM’s batching both allocate cache per sequence. If memory runs out under load but not in single tests, this is usually why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting order when you run out of memory
&lt;/h2&gt;

&lt;p&gt;Say you run Qwen3 32B (Q4_K_M) with Ollama on a 24 GB RTX 4090, set &lt;code&gt;num_ctx&lt;/code&gt; to 32768, and get out-of-memory errors or a sudden slowdown (layers spilling to CPU). The formula explains it: about 19.5 GB of weights plus about 8 GB of FP16 KV cache is more than 24 GB. Try these, least effort first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lower the context.&lt;/strong&gt; Back to 8192 and the KV cache is about 2 GB; total about 23 GB — it runs, but tight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quantise the KV cache.&lt;/strong&gt; With &lt;code&gt;OLLAMA_FLASH_ATTENTION=1&lt;/code&gt; and &lt;code&gt;OLLAMA_KV_CACHE_TYPE=q8_0&lt;/code&gt;, the same memory holds roughly twice the context — about 24k by the formula (a ceiling; leave headroom).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check parallelism.&lt;/strong&gt; Set &lt;code&gt;OLLAMA_NUM_PARALLEL=1&lt;/code&gt; to rule out several slots sharing the memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change cards.&lt;/strong&gt; Still short? Move to a 32 GB RTX 5090 or a 48 GB RTX 4090 48G. Switching means waiting about 2 minutes for the new instance and downloading the model again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After each change, check real usage with &lt;code&gt;nvidia-smi&lt;/code&gt; and note the number; next time you size a card, you will have your own data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking a card from the numbers
&lt;/h2&gt;

&lt;p&gt;Once you have weights + KV + overhead, round up to the next VRAM class and check &lt;a href="https://cloudgpu.app/deploy" rel="noopener noreferrer"&gt;Deploy&lt;/a&gt; for live stock. List prices on 2026-10-23 23:58 Beijing time: RTX 4090 24G $0.33/h, RTX 5090 32G $0.59/h, RTX 4090 48G $0.65/h, A800 80G $1.09/h, A100 80G $1.49/h, billed per minute. Instances start in about 2 minutes. For a side-by-side of those cards, see &lt;a href="https://cloudgpu.app/compare/rtx-4090-vs-5090-vs-a100" rel="noopener noreferrer"&gt;RTX 4090 vs RTX 5090 vs A100&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do I calculate the KV cache size for a model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multiply 2 × layers × KV heads × head dimension × bytes per value (2 for FP16) to get bytes per token, then multiply by context length and the number of parallel sequences. The values are in the model’s config.json.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much VRAM does a 32k context need for Qwen3 32B?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;About 8 GB of FP16 KV cache (256 KiB per token × 32,768 tokens), on top of about 19.5 GB of Q4_K_M weights, so a 32 GB card is the comfortable choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does my model run out of memory only at long context?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The weights are fixed, but the KV cache grows with every token of context and with each parallel request. Lower num_ctx / max-model-len, reduce parallel slots, or quantise the KV cache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does an 8-bit KV cache halve memory?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, the cache itself is halved compared with FP16. In Ollama set OLLAMA_KV_CACHE_TYPE=q8_0 with flash attention on; in vLLM use --kv-cache-dtype fp8.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the formula work for every model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It works for standard and grouped-query attention. Models with sliding-window layers or latent attention use less memory than it predicts.&lt;/p&gt;




&lt;p&gt;Once you have your own numbers, the &lt;a href="https://cloudgpu.app/compare/rtx-4090-vs-5090-vs-a100" rel="noopener noreferrer"&gt;RTX 4090 vs RTX 5090 vs A100 comparison&lt;/a&gt; lines up the cards by VRAM class. &lt;em&gt;Originally published at &lt;a href="https://cloudgpu.app/blog/kv-cache-vram-context-length-calculator-2026" rel="noopener noreferrer"&gt;cloudgpu.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CloudGPU (cloudgpu.app) has no partnership with, authorization from, or endorsement by the model vendor. Model names are trademarks of their owners. Context ceilings are estimates under the stated assumptions, not measurements. Prices are list prices read on 2026-10-23 23:58 Beijing time (UTC+8); live prices and stock on &lt;a href="https://cloudgpu.app/deploy" rel="noopener noreferrer"&gt;/deploy&lt;/a&gt; take precedence.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>llm</category>
      <category>gpu</category>
      <category>machinelearning</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
