The cheapest AI feature I have shipped and the most expensive one did roughly the same job. The difference was never the model anyone picked in a planning meeting. One of them ran when a user pressed a button, and the other ran every time the editor autosaved.
Token prices are rarely the reason an AI feature costs too much. The usual reason is a call site that fires far more often than anyone intended. The cache misses that follow, and an invoice nobody has ever broken down by feature, are what keep it hidden until the card gets charged.
So this is the version I wish someone had handed me before my first OpenAI integration: what the numbers are today, where the money actually leaks, and the order to build the controls in.
What Does It Actually Cost to Add ChatGPT to a SaaS?

A well-routed ChatGPT feature costs cents per active user per month; a badly routed one costs dollars, and model choice explains most of the gap.
Here is the current shape of it, straight from OpenAI's own pricing page, per million tokens:
| Model | Input | Cached input | Output | What I actually use it for |
|---|---|---|---|---|
| gpt-5.6-luna | $0.20 | $0.02 | $1.20 | The default. Classification, extraction, tagging, short user-facing replies, anything I can pin to a JSON schema. |
| gpt-5.6-terra | $2.00 | $0.20 | $12.00 | Escalation only. Multi-step reasoning, long documents, output a customer will read line by line. |
| gpt-5.6-sol | $4.00 | $0.40 | $20.00 | Rarely. And note the asterisk below. |
Two things in that table matter more than the absolute numbers.
The first is the ratio inside each row. Output bills at six times input on Luna, ten times on Sol. Most cost-control advice obsesses over shrinking the prompt, which is the cheap half of the transaction. Setting a hard max_tokens and asking for structured output instead of prose will usually save you more than an afternoon of prompt golf.
The second is that asterisk. Sol's $4.00 and $20.00 are promotional, and OpenAI's docs say that pricing holds "at least through November 21, 2026". If your unit economics only work at the promotional rate, you do not have unit economics. You have a countdown.
Worth knowing how we got here, because it moved recently and in one direction. On 30 July 2026, OpenAI cut Luna by 80% and Terra by 20% while leaving Sol's list price alone. The cheap tier got dramatically cheaper; the flagship did not. That is a strong hint about where the vendor expects production volume to live, and it should be a hint about where yours lives too.
Route First, Escalate on Evidence

Send every request to the cheapest model that can do the job, and escalate a specific request to a bigger model only when something measurable says the small one failed.
The failure mode here is not picking the wrong default. It is having no escalation signal at all, so the team quietly promotes the whole feature to a larger model after one bad demo and never demotes it. That single decision, made in an afternoon by someone who was tired, is the biggest line item on most AI bills I have looked at.
A usable escalation signal has to come from the response rather than from vibes. Three that work in practice: the model returned a schema-invalid object, a required field came back null or empty, or your own validator rejected the answer. All three are cheap to check and none of them require a second model call to evaluate. Retry once on Terra when one fires, log the escalation, and then go read that log weekly. If a particular prompt escalates 40% of the time, it does not need a router. It needs a better prompt or a bigger default.
Have you ever opened your usage dashboard and been unable to say which feature made up half the bill? That is the same problem wearing a different coat, and the next two sections are both about it.
Why Is My Prompt Cache Not Hitting?

Prompt caching matches on the exact rendered prefix, so a timestamp or a username near the top of your system prompt silently cancels the discount on every request.
This is the single most expensive detail in the whole integration, and it is documented plainly in OpenAI's prompt caching guide where almost nobody reads it. Cached input bills at 10% of standard input. On Luna that is $0.02 instead of $0.20. The matching is not fuzzy and it is not a hash of the semantic content — the system compares the entire rendered prefix, and if any content changes before a breakpoint, nothing after that change can match.
Which means the following, all of which I have seen shipped:
You are a helpful assistant. Today is {{date}}.at line one of the system prompt. Every request is a cache miss, forever, and nothing in the API response tells you off.- Injecting the current user's name and plan tier above the instructions instead of below them.
- Rebuilding a tool schema from a dictionary that does not preserve key order.
There is a second trap for small features. On GPT-5.6 and later the cache needs 1,024 visible input tokens before it engages at all. A tight little classification prompt of 300 tokens never caches, no matter how many million times you call it. Sometimes the correct move is to make the system prompt longer with genuinely useful few-shot examples, pushing it over the threshold, so that the stable part starts billing at a tenth of the rate.
Ordering is the whole discipline. Static instructions, then examples, then tools, then the conversation, then this request's variable content last. Once the prefix is stable, research on semantic caching by Regmi and Pun found that adding a similarity layer on top removed up to 68.8% of API calls outright on repetitive query mixes. Prompt caching makes each call cheaper. Semantic caching stops some calls from happening. Stack them in that order, because the first one is a config change and the second is a system you will have to maintain.
The Feature Nobody Uses Is Still Billing You
Cost attribution per feature is the control that catches the failures the other controls cannot see, because a runaway call site produces no errors at all.
The clearest public example I know is Arpit Gupta's write-up of a $1,800 mistake. A batch report generator got wired into the autosave hook. Every thirty seconds. Per open session. The bill went from $620 to $2,480 across 23 days with no new features shipped. The fix, moving the call back behind the manual export button, cut the following month by 61%.
The part worth sitting with is that the error rate was zero. Perfect response codes, normal latency, nothing in the per-request logs that looked wrong, because nothing was wrong at the request level. Each individual call was exactly what the code asked for. Only cost grouped by feature over time showed the shape of it.
So tag every call with the feature name and the tenant id before you ship the feature, not after your first surprise. On a multi-tenant setup (and if that phrasing is new, here is what B2B SaaS actually means in practice), the tenant tag is also how you find the one customer whose usage pattern is quietly subsidised by everyone else.
Tier Limits Arrive Before Your Budget Does
New accounts start at Tier 1 after $5 of cumulative spend, and Tier 5 needs $1,000 plus 30 days since your first payment. The calendar half is a hard floor. You cannot buy your way past it on launch week. Plan the launch around the tier you will actually be in, not the one you will qualify for a month later.
What Should You Charge for an AI Feature?
Price the AI feature as a variable-cost product from day one, because inference turns a fixed-cost line into a per-use one and quietly resets the margin the whole business was modelled on.
Traditional software runs at 70–90% gross margin. Bessemer's data on AI-first companies, summarised well by Monetizely, puts fast-scaling AI SaaS startups nearer 25% in their early stages, with steadier ones around 60%. A gap that wide changes what the word "unlimited" is allowed to mean on your pricing page.
Actually, that is too strong as a blanket claim. Those figures describe companies whose entire product is inference. If ChatGPT is one feature inside a product that already does something useful, whatever SaaS means for your particular category, your blended margin barely moves, because the AI is a thin slice of both the value and the cost. The trap is somewhere between those poles: an AI feature marketed as the headline reason to upgrade, priced flat, used hardest by exactly the customers on the cheapest tier.
Three patterns that survive contact with real usage:
- A generous monthly allowance per seat, with overage priced at roughly 3–4x your marginal cost. Most users never touch the ceiling and the ceiling stops the pathological ones.
- Credits denominated in something the customer already counts, such as documents processed or minutes of transcript, rather than in tokens they have no way to estimate.
- AI held behind the higher tier entirely, which is the lazy option and also the right one for a first release, because it caps your blast radius while you learn what usage actually looks like.
I built Callidus OS, a multi-tenant clinic SaaS on React, Firebase and Stripe Connect, solo in about ten weeks. The lesson from that build that transfers directly here: every per-tenant variable cost you do not meter on day one becomes a per-tenant variable cost you cannot meter later without a migration. Meter first. Decide what to charge afterwards.
Wire the Guardrails Before the Feature
If you are starting this week, do it in this order. The order matters more than any individual step, because each one makes the next one measurable.
- Set a hard spend limit in the OpenAI dashboard. Below what would hurt. This is your last line of defence and it takes ninety seconds.
- Pick Luna as the default and write down the escalation rule in the code, as a function, not in a Notion doc.
- Structure the prompt for caching: static content first, per-request content last. Then verify with the
cached_tokensfield in the response that you are actually getting hits. Do not assume. - Cap
max_tokensper call site. Output is the expensive half. - Tag every call with feature and tenant so cost attribution exists before you need it.
- Add a per-tenant rate limit in your own application layer, above whatever OpenAI enforces. Yours can return a friendly message; theirs returns a 429.
- Only then, add semantic caching, batching, or a fallback provider.
Steps 1 to 6 are an afternoon. Step 7 is a project, and most products never need it. If you want the wider version of how I sequence this kind of work, the AI-augmented development workflow I actually use covers the habits around it, and which AI solutions earn their place in a business covers whether the feature should exist at all. For the infrastructure underneath, the SaaS MVP stack I recommend is where I would start.
The leak is almost never where anyone expects it. Most often it is something dull, like a summarisation call sitting inside a list component that re-renders on scroll, or a retry loop with no ceiling behind a flaky third-party call. Nothing in the request logs looks wrong, because at the request level nothing is.
Go open your usage dashboard right now and try to name the top three features by spend. If you cannot, that is the thing to build tomorrow, and the model you chose is not the problem worth solving this week.
