AI costs are confusing. Providers give you a lot of numbers and nothing to actually know how much you are going to pay in the long run. There is no point in these input/cached/output token prices if you have no idea how many reasoning tokens you'll spend on your tasks. How much will be cached. We are going to review the real-world usage of 27 frontier models.
You cannot even compare different models because they reason differently. Some providers charge for the cache storage, some provide different caching strategies, some apply rates for busy hours, some...
And it's only the text. Image and voice are even more confusing.
So, collecting cost metadata from responses is the only way. This article is based on 51,000 AI calls in my AI Werewolf text game. Pure statistics out of my wallet.
AI in text games
My text game is nothing but a group chat with a human player and 5-15 bots. It's a long conversation with some role-play, rule following, periodic compactions. I wrote about its design earlier in How to make LLMs play conversational games. This can work for any text game with AI. I support 27 LLMs from all major labs, image generation for avatars and illustrations, voice for input and output. I also use classifiers on user inputs. AI is all around the place. And it costs money.
Since mid-September, every AI call the game makes writes one row to a stats table: tokens in, tokens out, cached tokens, cost and time. That is 53 days and about 51,000 calls so far. It's a lot of data, and we'll go through it together.
I pay for free users
Yeah, someone has to pay for API calls, and this someone is me. I have a paid tier, but the only user in it is me. My other 651 users are on the free tier. And it is generous - I let each of them spend up to $5 of my money daily. I don't restrict anything except the most expensive models. Mainly because the retention is low - people come and go. I don't see the point in pushing payments. And free users are awesome testers, especially when they are looking for ways to cheat and trick me.
I know, I know, it's easy to go bankrupt with such a strategy. All my friends who are into startups would call my approach rather questionable. But it kind of works - I have people playing without ads or ugly tricks like throwing banners with special offers. I track all clicks and calls, I'll be notified by Marlow on anything abnormal within 5 minutes. So I'm ready to reconsider it when the situation changes.
How much I spend a day
I have 6 unique users daily.
$6.36 a day on average. A typical day is a little under $6. The cheapest day was under 30 cents and the worst was about $16. The last 30 days are higher, at about $7, because more people are playing.
| Category | 53 days | Per day | Share |
|---|---|---|---|
| Text (bots, Game Master, story) | $212.30 | $4.01 | 63% |
| Images (portraits, scene illustrations) | $94.66 | $1.79 | 28% |
| Audio (bot voices, speech to text) | $28.29 | $0.53 | 8% |
| Classifiers (who speaks next, content screen) | $1.96 | $0.04 | 0.6% |
| Total | $337.21 | $6.36 |
A real game (50 turns or more) costs $1.49 on average: $1.03 of text, $0.32 of images, $0.13 of voice. It takes about 165 AI turns.
What's in a turn
It's an action taken by a bot. A reply to the chat, a vote, a night activity. I send the request with the context to an official LLM API and get back the bot's response. I count the cost of all the tokens in both - the response message contains this information.
I compare my 27 models by the cost of the average turn. I track different types of turns:
| Bot turn | Share of turns | Tokens in | Of those, cached | Tokens out | Cost per turn |
|---|---|---|---|---|---|
| Introduction | 13% | 3,690 | 504 (14%) | 299 | 0.30¢ |
| Day discussion | 46% | 8,218 | 3,544 (43%) | 428 | 0.41¢ |
| Vote | 19% | 10,094 | 1,987 (20%) | 511 | 0.60¢ |
| Night action | 10% | 11,950 | 3,254 (27%) | 503 | 0.65¢ |
| End-of-day summary | 11% | 13,545 | 945 (7%) | 1,124 | 1.00¢ |
| Post-game chat | 1% | 12,313 | 4,101 (33%) | 348 | 0.55¢ |
The summary is my compaction step. At the end of each day, every bot reads the day and rewrites its own notes. It's the most expensive turn in the game: it has the largest input, the most output and almost no cache. Summaries are 11% of bot turns and 21% of bot spend.
Context grows as the game goes on. A discussion turn starts at about 6,600 input tokens on day 1 and reaches about 11,400 on day 5. A summary goes from about 12,100 to about 16,800.
Some calls aren't bot turns:
| Other calls | Tokens in | Of those, cached | Tokens out | Cost per call |
|---|---|---|---|---|
| Story generation for a new game | 12,218 | 2,389 (20%) | 4,309 | 0.85¢ |
| Game Master narration, all kinds | 2,114 | 13 (1%) | 595 | 0.16¢ |
| Router (who speaks next), Jev | 3,400 | 0 | 0 | 0.014¢ |
| Router backup, GPT-6 Luna | 3,814 | 0 | 0 | 0.038¢ |
| Content screen, Jev | 788 | 0 | 0 | 0.003¢ |
| Content screen backup, GPT-6 Luna | 1,415 | 0 | 0 | 0.014¢ |
Output tokens are the trickiest ones because they include the response text + all the reasoning. They are very unpredictable because you have no idea how much a model is going to reason.
The four bands of LLMs
Text is the biggest part, so I'll start there. My game sorts every text model into one of four bands, based on what one bot turn costs. The band decides how many bots of that model a free game can have.
| Cost per turn | Bots in a free game | Share of turns | Share of bot spend |
|---|---|---|---|
| Up to 0.3¢ | Unlimited | 56% | 12% |
| Up to 1¢ | 3 | 21% | 25% |
| Up to 2¢ | 1 | 16% | 31% |
| Over 2¢ | Paid only | 7% | 33% |
The bands didn't start this way. I used to set the limits from the output price. It looked reasonable. It was wrong, as you'll see in the paid-only section. On September 20 I switched to the measured cost per turn. The free-tier cost per turn went from 0.91 cents to 0.67 cents in the next 30 days, and to 0.50 cents in the last 30 days. Cheaper new models helped too, so I can't give all of that to the change. But I should have measured from the start.
The tables below show models with at least 100 calls in the last 30 days, or the small samples I point out.
Unlimited: up to 0.3¢
| Model | Company | Cost per turn | Median reply | Slowest 10% |
|---|---|---|---|---|
| GPT-6 Luna | OpenAI | 0.09¢ | 4.8s | 11.6s+ |
| DeepSeek V4.1 Flash | DeepSeek | 0.09¢ | 2.6s | 7.2s+ |
| Qwen 3.8 Flash | Alibaba | 0.10¢ | 11.6s | 22.9s+ |
| MiniMax M3.1 Flash | MiniMax | 0.10¢ | 3.9s | 10.6s+ |
| GLM-5.3 Flash | Zhipu | 0.13¢ | 5.6s | 16.7s+ |
| Mistral 4 Small | Mistral | 0.17¢ | 5.2s | 10.1s+ |
| Claude Haiku 5.5 | Anthropic | 0.19¢ | 4.8s | 9.1s+ |
| Gemini 3.5 Flash Lite | 0.21¢ | 1.0s | 1.6s+ |
Yep, all the small frontier models from everybody. I'm not including reasoning efforts and output budgets in the table to save space and sanity. But I spent a lot of time balancing those things to get decent speed and performance.
Luna is as cheap as DeepSeek Flash. GLM and Qwen Flash are slow.
Up to 3 bots: up to 1¢
| Model | Company | Cost per turn | Median reply | Slowest 10% |
|---|---|---|---|---|
| DeepSeek V4 Pro | DeepSeek | 0.55¢ | 10.3s | 30.0s+ |
| GPT-6.1 Terra | OpenAI | 0.74¢ | 3.1s | 6.1s+ |
| GLM-5.3 | Zhipu | 0.93¢ | 5.0s | 15.6s+ |
| Gemini 3.8 Flash | 0.93¢ | 10.0s | 16.6s+ |
Gemini 3.8 Flash surprised me in a bad way. The jump from Flash Lite is big. It costs 4.4 times as much per turn and takes 10 times as long to reply. It charges more per token, and it writes about 800 output tokens a turn where Flash Lite writes about 80. Most of those 800 are reasoning.
DeepSeek Pro is slow: 10.3 seconds for a median reply. Full-size GLM is twice as fast as Gemini 3.8 Flash.
GPT-6.1 Terra is nice. It got much cheaper relative to GPT-5.6 and it's very fast. Good job, OpenAI.
1 bot: up to 2¢
| Model | Company | Cost per turn | Median reply | Slowest 10% |
|---|---|---|---|---|
| Qwen 3.8 Max | Alibaba | 1.02¢ | 10.5s | 25.7s+ |
| Mistral Large 4 | Mistral | 1.30¢ | 17.2s | 27.3s+ |
| Muse Spark 1.3 | Meta | 1.31¢ | 10.1s | 23.6s+ |
| Kimi K3.1 Pro | Moonshot | 1.47¢ | 13.3s | 34.1s+ |
| Gemini 4 Argon | 1.63¢ | 10.8s | 28.3s+ |
All the losers are here. Expensive and slow. Kimi K3.1 has a faster version at double the price. Mistral Large 4 and Muse throw 1 min timeouts on summaries quite often.
I keep these models for diversity. They are not very practical for my game. Sometimes I move a more expensive model to this band to let users try it. And to collect some data.
Paid only: over 2¢
| Model | Company | Cost per turn | Compared to Luna | Calls |
|---|---|---|---|---|
| Claude Fable 5.1 | Anthropic | about 10.6¢ | 128x | 27 |
| Grok 4.7 | xAI | 4.89¢ | 59x | 29 |
| GPT-6 Astra | OpenAI | 4.38¢ | 53x | 25 |
| Claude Sonnet 5.5 | Anthropic | 3.13¢ | 38x | 955 |
| Gemini 3.1 Pro | 2.94¢ | 35x | 458 | |
| Claude Opus 5.5 | Anthropic | not enough data | - | - |
| GPT-6.1 Sol | OpenAI | not enough data | - | - |
| Muse Wonder 1.0 | Meta | not enough data | - | - |
| Sakana Fugu Max | Sakana | not enough data | - | - |
Fable is more than 100x more expensive than Luna. I don't have many numbers in this section - most of the models here have never been played by anyone except me.
Grok and Gemini Pro. In the 30 days before I changed the rule, Grok 4.6 was allowed three bots a game, because its output price was only $6. It cost 3.55 cents a turn and was the most expensive model in the app. Gemini 3.1 Pro was second at 2.80 cents. Together they were about 12% of the turns and 39% of the bot spend: $43.75 of $111.52. Meanwhile GLM-5.3, with a lower output price of $4.40, was limited to one bot and cost 0.76 cents.
That was my poor balancing based on the provider's token price. Having the stats helped me to adjust the bands. The worst part is that players don't even care about the models that much - it was the random selection in my code that put those models into games because they were considered affordable.
Mistral Medium 3.5. I then repeated the mistake. The new system gave it one seat per game. Its reasoning spiked to 15,000-24,000 tokens on some turns. It cost 3.5 cents a turn, and about 6% of its calls failed. I removed the model three weeks later. It cost me $12.32.
Sonnet and Haiku. On October 13 I gave Sonnet 5.5 one seat per free game, to collect samples. Over the same weeks:
| Input tokens | Output tokens | Median reply | Cost per turn | |
|---|---|---|---|---|
| Claude Haiku 5.5 | 13,255 | 784 | 4.8s | 0.18¢ |
| Claude Sonnet 5.5 | 12,231 | 460 | 4.2s | 3.10¢ |
Sonnet costs 17 times as much per turn and it isn't faster. In its last week it was $11.35 of the $12.22 of Claude spend in my stats, nearly all from free games, from one seat per game.
Token price vs. effective price
This is how much the real price differs from what I expected from the input/output rate. For the expected price I took a turn of 8,000 tokens in and 300 out at the rate card, with no cache. Then I divided the real average turn cost by it.
| Model | Real cost vs expected |
|---|---|
| Grok 4.7 | 2.7x |
| Mistral Medium 3.5 | 2.5x |
| Mistral Large 4 | 2.1x |
| Gemini 3.1 Pro | 1.5x |
| Gemini 3.8 Flash | 1.3x |
| GPT-6.1 Terra | 0.8x |
| Kimi K3.1 Pro | 0.8x |
| GLM-5.3 | 0.7x |
| Qwen 3.8 Max | 0.6x |
The models under 1x are there because of caching. Without the cache, at the same token counts, Terra, GLM and Kimi would be at about 1.0x, and Qwen Max at 1.2x. Qwen Max reads 63% of its input from the cache, more than any other model here, so it goes from above the line to the cheapest ratio in the table. The models at the top write a lot more than 300 tokens a turn, and no cache discount covers that.
The hidden variable is reasoning. Grok 4.6/4.7 wrote about 2,200 output tokens a turn, and 94% of them were reasoning. Players saw about 100 of them. Not every provider reports the split, so I can't do this for all of them.
Another hidden thing is a tokenizer. Different models produce different amount of input tokens on the same text. Claude Haiku 5.5 averaged 13,473 input tokens a turn. GPT-6 Luna averaged 7,377 in the same kind of game.
The myth of cheap Chinese models
The common story is that Chinese models are far cheaper than American ones. On average, in my data, that even looks true: a turn on a Chinese model cost 0.40 cents and a turn on everything else cost 0.76 cents.
Compare the models inside each band and the gap is gone. The bands are balanced, and neither side wins. I was surprised to see that Luna goes head to head with DeepSeek Flash.
The one exception is DeepSeek V4 Pro. At 0.55 cents a turn, it is the cheapest model in the 3-bot band, below GPT-6.1 Terra (0.74 cents) and Gemini 3.8 Flash and GLM-5.3 (0.93 cents each).
Chinese models are also slower. I wrote about that in August in How I tried to write an article about slow Chinese LLMs. DeepSeek Flash V4.1 is the exception. It has a median reply of 2.6 seconds, one of the fastest in the game.
Caching is super tricky
Input is the biggest part of my text bill: about 73% of it, compared to 27% for output. The prompt also grows as the game goes on, from about 6,900 tokens on day 1 to about 15,500 on day 8. Almost all of that prompt is the same from one turn to the next. Providers sell cached input at 75-98% off. On paper, caching should fix everything.
In practice, only 29% of my input tokens were served from cache.
The first reason is the pace of the game. Coding agents call a model every few seconds. My bots wait for a human to type, and for other bots to talk. The median time between two calls from the same bot is 4 minutes. 42% of the gaps are over 5 minutes and 6% are over 30.
Here is the share of input tokens served from cache, depending on how long the bot had been silent.
| Gap between a bot's calls | <1m | 1-5m | 5-15m | 15-60m | 60m+ |
|---|---|---|---|---|---|
| Share of all turns | 11% | 47% | 29% | 9% | 4% |
| DeepSeek | 68% | 56% | 48% | 49% | 45% |
| Claude (1-hour cache) | 51% | 45% | 42% | 41% | 7% |
| Qwen | 87% | 70% | 36% | 21% | 3% |
| OpenAI | 31% | 23% | 19% | 13% | 0% |
| GLM | 38% | 27% | 16% | 2% | 0% |
| Mistral | 42% | 21% | 6% | 2% | 0% |
| Gemini | 36% | 16% | 2% | 1% | 0% |
The table says a few things:
- DeepSeek doesn't care about my pace. It hit on 100% of repeat calls, even after an hour. Its cache lasts hours or days. It's the only one built for a game like this.
- Gemini is effectively off. After 5 minutes it's gone. Gemini 3.8 Flash is one of the models I spend the most on, and only 10% of its input was cached.
- Qwen is the best deal when you're quick. Qwen Max got 63% of its input from cache, and that saved it nearly half its bill.
- Slowness isn't the whole story. OpenAI's cache is supposed to last 30 minutes, but it only served 31% of the tokens even when the gap was under a minute. I don't know why. The bot's call may just land on a different server.
The second reason surprised me, because I had blamed pace for everything. Here is the same cache share by type of turn:
| Gap between a bot's calls | <1m | 1-5m | 5-60m |
|---|---|---|---|
| Day discussion | 55% | 51% | 33% |
| Night action | 52% | 16% | 13% |
| Vote | 25% | 23% | 15% |
| End-of-day summary | 26% | 7% | 6% |
Even with a short gap, votes and summaries barely hit. A discussion turn right after another discussion turn gets 60% within 5 minutes. A vote right after a discussion turn gets 23%. On OpenAI and Gemini, votes and summaries within 5 minutes get 0-2%.
After my previous article I reworked the caching logic. I stopped sending the system prompt twice to OpenAI, moved Claude to the 1-hour cache, and kept the repeated part of every prompt the same byte for byte. I thought I did a good job. Nope.
The vote problem is structured output. Discussion turns ask for plain text. Votes and night actions ask for JSON in a fixed format, and each night role has its own format. The history is the same, so the cache should still work. Apparently not, at least not for every provider. Here is the cache share of a vote that comes within 5 minutes after the same bot's discussion turn:
- OpenAI, Google, Mistral, Meta: 0-3%. All four take the JSON schema as a separate request setting, and the switch throws the cache away.
-
Anthropic: 25%. Anthropic's docs say this: with structured output, "Claude automatically receives an additional system prompt explaining the expected output format," and "changing the
output_config.formatparameter will invalidate any prompt cache for that conversation thread." The 25% that survives is the game rules at the top of the system prompt. - DeepSeek, GLM, MiniMax, Qwen, Kimi: 41-76%. DeepSeek, GLM and MiniMax get the schema as text at the end of the prompt, so the start of the prompt doesn't change. Qwen and Kimi take a separate schema setting like OpenAI does, and still keep their cache.
Chinese models keep their cache much better on JSON turns.
The summary problem is my own mistake. The prompt gets some data injected, and this nukes the cache. I need to fix it. I didn't notice it until I pulled the data for this article.
Caching is tricky.
Having a cache might be more expensive than not having one
Anthropic's default cache lasts 5 minutes, and the median gap between a bot's calls is about 4 minutes. So in September I switched every Claude call to the 1-hour cache. It costs more. Writing to it costs twice the normal input price. Reading from it costs a tenth.
And this is what I got:
| Sonnet 5.5 | Cost per turn |
|---|---|
| No cache at all | 2.94¢ |
| With the 1-hour cache | 3.13¢ |
How is this possible?
The longer cache only pays off if most of what you write gets read back. Mine didn't. Over 53 days, Anthropic's usage report says 48% of Sonnet's input was written to the cache at double price, and only 42% was read back. Every switch to a JSON turn cleared the cache, and the bot wrote everything again.
My own stats didn't show it, because my code priced cache writes at the normal rate. I only found it when the Anthropic balance dropped about 1.5 times faster than my stats said it should.
Images: 28% of the bill
Images are a recent feature. I was hesitant to add them because of the extra costs. But they improved the UI/UX a lot, so I decided to try to keep them.
Every game draws a welcome scene and a sheet of portraits while it's being created, and then scene illustrations as the story goes on. All of it runs on Google's image models.
I try to keep it cheap - all avatars are generated as a single image map, then cut by the algorithm into pieces. I also let users regenerate the avatars - luckily they don't abuse this feature. The reason for regeneration was a lot of bugs in the early days of the image feature. A model produced bad maps, the algorithm could not cut them properly. I even added a simple editor to adjust the avatars.
| Image type | Calls | Spend | Before Oct 21 | After Oct 21 |
|---|---|---|---|---|
| Portraits and welcome scenes | 421 | $62.75 | 17.0¢ | 11.6¢ |
| Illustrations during the game | 585 | $31.91 | 6.9¢ | 4.3¢ |
The median game costs 20 cents in images.
A lot of games are created and never played. 97 games ended before 10 turns. They cost me $17.40, and $14.62 of that was images - quite a waste.
On October 21 I moved from Gemini 3.1 Flash Image to Nano Banana 2.1. It cut the average call from 12 cents to 6.7. My daily image spend still went up, from $1.67 to $2.06, because image calls per day more than doubled, from 14 to 31.
Image models reason too. The thought tokens bill as text, and at the API's default level a Nano Banana sheet costs more than the older model did. I run it at the minimal level. Same lesson as text: the price per image on the rate card isn't what you pay.
Audio: cheap, and growing
| Model | Job | Calls | Spend | Per call |
|---|---|---|---|---|
| GPT-4o Mini TTS | Bot voices | 3,034 | $15.52 | 0.51¢ |
| Gemini 3.8 Flash Lite TTS | Bot voices | 3,061 | $11.47 | 0.37¢ |
| Gemini 3.1 Flash TTS (preview) | Bot voices, until Sep 24 | 78 | $1.24 | 1.59¢ |
| Gemini 3.5 Transcribe and Whisper | Speech to text | 35 | $0.06 | 0.17¢ |
Gemini's voice is 27% cheaper per line than OpenAI's, and it's more than four times cheaper than the Gemini preview it replaced. Players pick the provider for each game, so both get used about equally.
72% of games used voice, 292 of 405. There is about one spoken line for every five messages. So it's popular and it still costs less than a third of what images cost.
It's growing, though. Audio cost $1.47 in the first week of this data and $6.13 in the last full week.
The speech-to-text feature is not popular. In 53 days people used it 35 times, for a total of 6 cents.
Classifiers: a quarter of the calls, 0.6% of the money
Two small classifiers run around the bots. The router decides which bots should reply next. The screen judges everything a human types, before it reaches a provider. This last one turned out to be necessary because too many users try to get nudes and other nasty stuff in the AI Werewolf text game. Sure, why not. I wrote a separate article about this, and I might do a few more because I got so many more fun cases.
I don't think it's bad, but if AI providers refuse too much, they might ban me. Not the user. Me, my API key. And it's getting trickier - Anthropic's 2026 usage policy update adds a ban on "sustained and needless abusive or cruel behavior toward our models." I cannot let this happen, and the classifiers are quite handy for this.
The main classifier is Jev from typesafe.ai. Since October 8, GPT-6 Luna runs next to it through OpenAI's Decisions API, on nearly every call. I added it because Jev sometimes fails or throws timeouts at me. Rarely, but this does happen.
Luna decides only if Jev fails. Otherwise its answer is saved so I can compare the two.
| Job | Model | Calls | Spend | Per call | Median time |
|---|---|---|---|---|---|
| Router | Jev | 3,461 | $0.49 | 0.014¢ | 82-149ms |
| Router | GPT-6 Luna | 2,598 | $0.99 | 0.038¢ | 201ms |
| Screen | Jev | 3,401 | $0.11 | 0.003¢ | 84-160ms |
| Screen | GPT-6 Luna | 2,555 | $0.36 | 0.014¢ | 327ms |
That's 12,015 calls, 24% of everything the game calls, for $1.96. It works out to under a cent per game.
Using Jev as the router was a huge improvement. It's very fast and cheap.
The only problem with classifiers is that they don't agree with each other. Jev and Luna give me very different scores on the same inputs and questions - I had to do a lot of tuning. They also give high scores to things I find harmless in the role-play context. Like a user calling themselves retarded (0.9 hate speech) or "Good italian is dead italian" (0.95 racism). I'll leave it for a separate article.
Tracking mistakes
I track all the costs by reading the metadata in responses. But something still slips. Comparing my numbers with the provider's usage report often shows a difference:
- DeepSeek: 9% under. No idea why.
- Gemini: close until mid-October, then 16-32% under. Probably my other projects on the same key that I forgot about.
- Claude: I paid 1.54x what I recorded. This one is not the shared key. Anthropic's usage report shows my token counts were right within 2%. The bug was in my code: it priced 1-hour cache writes at half their real price.
Need to do some digging.
What I'd tell myself a few months ago
- Don't choose models by the price per token. Run them on your real workload and divide the money by the calls.
- Don't assume the cache helps. Test it, read the docs, then test again. In the field, on real production use cases. Caching is the hardest part of working with an LLM API.
- Most users don't really care about the models. So, the random selection balanced around the cheapest models saved me tons of money. In the beginning, I just randomly picked models from the supported list.
- Use classifiers for the game logic where possible.
- Check your cost tracking against the balance every month. And in general, analyze statistics all the time.
The numbers keep growing
The Models page in AI Werewolf shows the effective cost per turn for every model in the game, measured from real games. I re-measure it as the stats grow, so it works as a benchmark that keeps updating.
It's biased. It reflects my use case, my bugs, and the cheap models people pick the most. But who said the other benchmarks are better? At least this one comes from the real world. Your project will probably look more like mine than like a generic benchmark.








Top comments (28)
Hi Aliaksei! Thank you to share your detailed AI cost and experience those information is very valuable for me. My game building idea is bit different. My game just use a partial AI instead of core mechanic. I don't register player, just let them play it. Maybe take a look:
Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼
Singularity News :: CCG
Nice work. However, our games are quite different. Your's doesn't seem to have any AI making decisions or actually playing. Which is probably a smarter use of AI. When I started mine, I haven't though about budgets and tokens - I just wanted to build it for myself. I only realized how expensive it is to run after the shipment.
I have to register users to track and limit the spendings. The fact than I only take their emails creates a lot of possibilities for the players to trick me. People create multiple accounts, use VPN + incognito mode to bypass my checks. It would be easier if I asked more info from the players, but try to stay aways from this as much as I can.
This is very interesting. Are you trending toward having enough paid users to cover your free users?
I am not, I have zero paying users. Someone tried recently, but Stripe rejected a credit card from Russia. I added crypto payments the same day, but the person never returned.
My plan was to get users, create a community, and only then start thinking of the monetization. I can always shrink the free tier features and limits but I haven't yet reached the level os spendings where I really have to do that.
The cache result that surprised me most was the 1-hour cache costing more — 3.13¢ a turn versus 2.94¢ with no cache at all — because the write premium only pays off if the cached tokens actually get read back. Pairing that with the structured-output finding, that votes and night actions barely hit cache because the JSON schema invalidates it for OpenAI, Google, Mistral and Meta, makes this feel like a field guide rather than a price list. The $6.36-a-day headline for six daily users is remarkably concrete too — did the Sonnet-versus-Haiku gap, 17x the cost per turn at the same speed, change which models you let into free games?
Yeah, it did. In the very beginning, I just select models randomly for each game. A player can always change that if they like. Now, the random selection allocate more sits to cheaper models and a player is limited in selecting expensive model combinations. Sonnet is too expensive for a free tier - even one model a game pushed the price up by a lot.
That schema result has a mechanical cause, and it is fixable. Schemas usually land after the variable part - tool definitions appended last, or the schema string pinned to the tail - so the shared prefix ends before them and every request forks at the same point.
Put the schema and the static instructions at the very front, keep per-request state and turn counters strictly at the tail: on the structured-output loads I have logged, prefix hit rate went up 40-70 points.
The write premium is the same effect read off the invoice - you paid to write a prefix that was never read twice.
@hiper2d Agreed for a welcome message. The cost is in long sessions, where the whole context goes out again on every turn: Tokenade cut session cost 39% on average in the THOL benchmark (2026-09-14, raw data public).
Sonnet 5.5 costs 17 times Haiku per turn, 3.10 cents versus 0.18, for a median reply only 0.6 seconds faster. At that gap, the expensive model only makes sense if the extra quality shows up in the game, not the latency.
The 1-hour cache costing more than no cache is the line that stuck with me — 3.13¢ vs 2.94¢ a turn, and the write premium only pays off if the prefix actually gets read back. I keep coming back to the free-tier math though: $5 a day per user, 651 free users, zero paying. How close have you actually come to the 'oh no' number, or does the alert just never fire because retention is that low?
The math is simpler if to look at the active or daily users only. It's $6-7 a day on average. The worst days I had were not because of sudden spikes but because of abusers - some players created multi-accounts and burnt me $20/day. But it's rare.
The 1-hour cache section hurts because it's so easy to walk into. With a chatty session-style loop the median gap between calls decides everything, and the 5-minute default was already borderline before the write premium got involved.
One question on the "every switch to a JSON turn cleared the cache" bit — is that because the serialized turn contains volatile fields (ids, timestamps) so the prefix diverges? If so, moving all the volatile fields to the end of the serialized block and freezing everything before it keeps the cached prefix stable even when the turn changes; that helped in a similar setup we ran.
Also curious: was the stats-pricing bug (cache writes priced at the normal rate) in your own metering layer, or were you reading cost from the response usage field? That distinction seems to decide whether you catch it in your own dashboard or only on the invoice.
I really don't see the reason to clear the cache when switching to the JSON mode mid-session. Chinese models don't do that. My case is probably rare, so nobody cares. It's just something to know about. I used to use JSON mode for everything but then I noticed that it takes longer - somehow the same input with the plain text response type can be easier for morels.
No provider hands us a dollar amount. I read the token breakdown from the response and then apply the costs from the config. So yeah, I had lots of bugs in this logic. Prices can be very tricky to follow. The cache storage price is a black box, responses don't reveal it.
Reasoning tokens bill as output, so in a long game that hidden line can outweigh the visible text.
Yes, outweighs by a lot. By default, many models tend to reason to the roof. 1000-4000 tokens on a simple question easily. I had to tune this down by lowering the reasoning effort and output budget in pretty much every Chinese model. It's nice when models support adaptive reasoning - this usually keep the output tokens tight on simple text questions.
Worth measuring the ratio rather than the absolute: reasoning tokens as a share of billed output. In multi-turn game loops I have seen 40-60% once the model starts planning moves, and the share grows with turn count because the visible reply stays short while the deliberation does not. Two cheap checks: log reasoning_tokens separately from output_tokens, and cap it per turn - an uncapped reasoner in a 20-turn session can spend more thinking about a move than the move itself costs.****
@hiper2d Same experience: effort had to be tuned by hand, model by model. THOL, 2026-09-14: 39% lower session cost on average on long Claude Code runs, raw data public.
Higher reasoning in coding usually makes sense. Although, yeah - it depends. In my case, it didn't make sense to reason on high for a simple welcome message to the chat.
The number to pin down is cost per playable turn, not cost per 1M tokens. A text game is mostly fixed system prompt plus world state, so a 4k-token prompt at $0.10/M costs $0.0004 per turn before the model writes a word. At 60 turns an hour that is $0.024/hour of pure prompt repetition - which dwarfs the output cost and is where prefix caching actually pays. Two things I would measure separately: cost of a turn the player accepts versus cost including retries, and what fraction of the prompt is a cacheable prefix. In my experience rejections eat 20-40% of the budget while looking like model cost.
I don't have any rejections. A user doesn't have an option not accept. Some request might fail with a timeout, there are some rare failures on the provider's end, certain images instructions can be locked by Google, but overall, rejected calls are not that significant cost-wise
Fair point - if there is no rejection path, my 20-40% figure does not apply here. The residual line I would still watch is requests that are billed but produce nothing usable: a timeout on the provider side or a policy block that fires after the prompt was already tokenized can still appear on the invoice. Called-out as rare, but on a long session it is a few percent, and without a billed-but-failed counter it hides inside the per-turn average and reads as model price. That counter is cheap: one integer per turn, next to the token count you already log.