Firsthand measurement of GLM-5.3-Flash, Qwen3.8-Max and Kimi K3 on DigitalOcean Serverless Inference, comparing what the pricing page implies against what the requests actually cost.
2,099 measured API calls. $13.98 total spend. Every number in the article is
regenerated from the raw logs by analyze.py.
This repository contains the frozen prompt sets, the measurement harness, the raw result logs, and the analysis that produces every figure we published. You can reproduce the whole study for about $14.
GLM-5.3-Flash lists at 1/12 of Qwen3.8-Max's output price and 1/30 of Kimi K3's. Measured on 24 identical prompts, five repetitions each:
| Model | List output price | Measured $/request | Realised advantage |
|---|---|---|---|
| glm-5.3-flash | $0.50 / 1M | $0.00156 | — |
| qwen3.8-max | $6.00 / 1M | $0.00361 | 2.3x, not 12x |
| kimi-k3 | $15.00 / 1M | $0.02661 | 17.0x, not 30x |
Flash is still the cheapest by a wide margin. But an engineer forecasting from list price will be roughly 2x wrong against Qwen.
Median output tokens on identical prompts:
| Model | Tier 1 (trivial) | Tier 2 (moderate) | Tier 3 (hard) | Longest single response |
|---|---|---|---|---|
| glm-5.3-flash | 625 | 3,141 | 5,018 | 15,006 |
| qwen3.8-max | 156 | 645 | 886 | 2,170 |
| kimi-k3 | 456 | 2,006 | 1,961 | 9,011 |
GLM-5.3-Flash spends 625 tokens answering "What port does SSH use by default?"
Median share of billed output tokens that are reasoning:
| Model | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| glm-5.3-flash | 0.72 | 0.81 | 0.84 |
| kimi-k3 | 0.65 | 0.77 | 0.82 |
| qwen3.8-max | — (thinking off by default) | — | — |
The single longest response we recorded was 15,006 tokens at a 94.7% thinking share, answering one deployment-architecture question.
enable_thinking does three different things on three modelsSame parameter, same platform, opposite outcomes:
| Model | Effect of enable_thinking: false |
|---|---|
| glm-5.3-flash | Cosmetic. reasoning_content empties, but unlabelled chain-of-thought appears in the visible answer in at least 103/120 responses. Output rises 20.9%, cost rises 11.1%. You pay more to see less. |
| kimi-k3 | Works. Output falls 67.9%, cost falls 75.5%, and per-call input overhead drops from 99 to 32 tokens. |
| qwen3.8-max | Already off. Turning it on raises output 429% and cost 508%. |
The GLM effect is strongest on trivial prompts (38/40 at tier 1, 31/40 at tier 3), which is the opposite of what proportional deliberation would predict.
Nine configurations, three models, one platform, 18.5x spread:
| Rank | Configuration | $/request | vs cheapest |
|---|---|---|---|
| 1 | glm-5.3-flash / default | $0.00156 | 1.00x |
| 2 | glm-5.3-flash / on | $0.00157 | 1.01x |
| 3 | glm-5.3-flash / off | $0.00174 | 1.11x |
| 4 | qwen3.8-max / off | $0.00359 | 2.29x |
| 5 | qwen3.8-max / default | $0.00361 | 2.31x |
| 6 | kimi-k3 / off | $0.00651 | 4.17x |
| 7 | qwen3.8-max / on | $0.02196 | 14.04x |
| 8 | kimi-k3 / default | $0.02661 | 17.01x |
| 9 | kimi-k3 / on | $0.02892 | 18.49x |
Kimi K3 configured well (4.17x) is cheaper than Qwen3.8-Max configured badly (14.04x). One parameter moves Kimi further than switching models does.
On 20 tasks with deterministic answers and a forced output format, 899 graded responses:
| Model | Mode | pass@1 | $/correct answer | vs cheapest |
|---|---|---|---|---|
| glm-5.3-flash | off | 100.0% | $0.00018 | 1.00x |
| glm-5.3-flash | default | 100.0% | $0.00018 | 1.01x |
| glm-5.3-flash | on | 100.0% | $0.00019 | 1.05x |
| qwen3.8-max | off | 100.0% | $0.00226 | 12.38x |
| qwen3.8-max | default | 100.0% | $0.00235 | 12.85x |
| kimi-k3 | off | 98.0% | $0.00282 | 15.45x |
| qwen3.8-max | on | 100.0% | $0.00383 | 20.98x |
| kimi-k3 | default | 100.0% | $0.00565 | 30.89x |
| kimi-k3 | on | 100.0% | $0.00601 | 32.90x |
897 of 899 responses correct. Accuracy did not differentiate the models at this task difficulty, so price is the only remaining variable. The cheap model is not cheap because it is worse — at this task class it is not worse at all.
Open-ended prompts versus structured tasks with a forced answer format:
| Model | Median out (open) | Median out (structured) | Reduction |
|---|---|---|---|
| glm-5.3-flash | 1,409 | 276 | 80.4% |
| kimi-k3 | 1,133 | 248 | 78.1% |
| qwen3.8-max | 435 | 144 | 66.9% |
GLM-5.3-Flash's cost advantage over Qwen3.8-Max goes from 2.3x on open-ended prompts to 12.8x under structured output; over Kimi K3, from 17.0x to 30.7x. Verbosity is what erodes the paper advantage, and output constraints suppress verbosity more on Flash than on anything else.
Adding "Answer in one sentence" cut output 70–91% across all three models — but thinking share was unchanged (GLM 0.72 → 0.77, Kimi 0.65 → 0.65). The instruction compresses the answer, not the deliberation.
prompts.jsonl 24 open-ended prompts across 3 difficulty tiers,
plus 8 brevity-control variants. Frozen before the first call.
tasks.jsonl 20 tasks with deterministic answers and a forced answer format.
pricing.json DigitalOcean rates used for every cost figure, with snapshot date.
run.py Measurement harness. Collects, splits reasoning from answer,
reconciles against billed tokens, resumable.
score.py Grades tasks.jsonl runs, reports cost per correct answer.
analyze.py Regenerates every published number and chart.
requirements.txt Pinned dependencies.
results/ Raw JSONL logs, one record per API call.
analysis/ numbers.md and four charts, generated by analyze.py.
python3.11 -m venv .venv && source .venv/bin/activate
python -m pip install -r requirements.txt
export DO_MODEL_ACCESS_KEY=...
# smoke test first: 12 calls, a few cents
python run.py --limit 4 --reps 1 --out results/pilot.jsonl
# open-ended prompts across all three thinking modes
python run.py --reps 5 --max-tokens 32000 --out results/core-default.jsonl
python run.py --reps 5 --max-tokens 32000 --thinking on --out results/core-on.jsonl
python run.py --reps 5 --max-tokens 32000 --thinking off --out results/core-off.jsonl
# brevity control
python run.py --reps 5 --max-tokens 32000 --variant brevity-control \
--out results/brevity.jsonl
# verifiable tasks
for mode in default on off; do
python run.py --prompts tasks.jsonl --variant verifiable --reps 5 \
--max-tokens 32000 --thinking $mode --out results/verify-$mode.jsonl
done
python score.py tasks.jsonl results/verify-*.jsonl
python analyze.py --results-dir results --tasks tasks.jsonl --out-dir analysis
run.py is append-only and resumable — it keys on prompt_id::model::rep, so an
interrupted run costs nothing to restart.
Platform. DigitalOcean Serverless Inference, OpenAI-compatible endpoint at
https://inference.do-ai.run/v1. Model IDs glm-5.3-flash, qwen3.8-max,
kimi-k3. All prices are DigitalOcean's, captured on one date and recorded in
pricing.json.
No sampling parameters. Temperature, top_p and penalties are never sent. Kimi K3 uses fixed sampling values, so setting them on the other two would introduce an asymmetry. All models run at platform defaults.
Non-streaming, max_tokens=32000. An earlier run at 8,000 right-censored 20%
of GLM's tier-3 responses; the reported run has zero truncated records and every
finish_reason is stop.
Randomised execution order. The full model x prompt x repetition matrix is shuffled with a fixed seed, so platform drift spreads evenly rather than landing on whichever model ran last.
Token accounting. DigitalOcean's usage object does not break out reasoning
tokens (completion_tokens_details is null), but models expose deliberation in
a reasoning_content field on the message. We tokenize that locally with each
model's own tokenizer and reconcile against billed completion_tokens. The
residual is a constant per-model chat-template offset — GLM +2, Qwen +1, Kimi +13
— which confirms the tokenizers are correct. Shares are reported against billed
tokens, with the offset left in.
Medians, not means. Output length has a long right tail (GLM's mean is 3,111 against a median of 1,409; coefficient of variation 1.01). Means overstate typical cost. Five repetitions support a median and a range, not a tight confidence interval.
Unlabelled chain-of-thought is detected by a keyword heuristic on the visible
answer. It is a floor, not a census: it caught 103 of 120 GLM thinking-off
responses, and manual inspection suggests the true rate is higher. All
quantitative claims use billed completion_tokens, which is unambiguous.
v20, all 45 responses answered 43 and
our key said 42. The models were right; the key failed to account for the first
token arriving at TTFT. Corrected, and disclosed here.completion_tokens exceeded returned reasoning plus answer tokens by
85–391 tokens. We could not account for the difference. GLM and Qwen show no
such tail.pricing.json; re-run before relying on these
figures.Each line of a results file is one API call. Fields of interest:
| Field | Meaning |
|---|---|
completion_tokens | Billed output tokens. Authoritative. |
reasoning_tokens_local | Reasoning tokens, counted locally with the model's tokenizer |
answer_tokens_local | Visible answer tokens, same method |
reconciliation_gap | completion_tokens - (reasoning + answer). Constant per model. |
thinking_share | reasoning_tokens_local / completion_tokens. Null when reasoning was not separable — never zero. |
split_source | reasoning_content, think_tags, or none |
content_cot_suspected | Unlabelled deliberation detected in the visible answer |
thinking_mode_requested | default, on, or off |
cost_usd | Computed from pricing.json. Cached tokens are a subset of prompt_tokens, not an addition. |
truncated | finish_reason == "length". Exclude from length analysis. |
reasoning_text / answer_text | Full text, retained so the split is auditable |
Corrections welcome — open an issue. If you re-run this and get different numbers, we would like to know.
7 commits
Python
100.0%
Firsthand measurement of GLM-5.3-Flash, Qwen3.8-Max and Kimi K3 on DigitalOcean Serverless Inference, comparing what the pricing page implies against what the requests actually cost.
2,099 measured API calls. $13.98 total spend. Every number in the article is
regenerated from the raw logs by analyze.py.
This repository contains the frozen prompt sets, the measurement harness, the raw result logs, and the analysis that produces every figure we published. You can reproduce the whole study for about $14.
GLM-5.3-Flash lists at 1/12 of Qwen3.8-Max's output price and 1/30 of Kimi K3's. Measured on 24 identical prompts, five repetitions each:
| Model | List output price | Measured $/request | Realised advantage |
|---|---|---|---|
| glm-5.3-flash | $0.50 / 1M | $0.00156 | — |
| qwen3.8-max | $6.00 / 1M | $0.00361 | 2.3x, not 12x |
| kimi-k3 | $15.00 / 1M | $0.02661 | 17.0x, not 30x |
Flash is still the cheapest by a wide margin. But an engineer forecasting from list price will be roughly 2x wrong against Qwen.
Median output tokens on identical prompts:
| Model | Tier 1 (trivial) | Tier 2 (moderate) | Tier 3 (hard) | Longest single response |
|---|---|---|---|---|
| glm-5.3-flash | 625 | 3,141 | 5,018 | 15,006 |
| qwen3.8-max | 156 | 645 | 886 | 2,170 |
| kimi-k3 | 456 | 2,006 | 1,961 | 9,011 |
GLM-5.3-Flash spends 625 tokens answering "What port does SSH use by default?"
Median share of billed output tokens that are reasoning:
| Model | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| glm-5.3-flash | 0.72 | 0.81 | 0.84 |
| kimi-k3 | 0.65 | 0.77 | 0.82 |
| qwen3.8-max | — (thinking off by default) | — | — |
The single longest response we recorded was 15,006 tokens at a 94.7% thinking share, answering one deployment-architecture question.
enable_thinking does three different things on three modelsSame parameter, same platform, opposite outcomes:
| Model | Effect of enable_thinking: false |
|---|---|
| glm-5.3-flash | Cosmetic. reasoning_content empties, but unlabelled chain-of-thought appears in the visible answer in at least 103/120 responses. Output rises 20.9%, cost rises 11.1%. You pay more to see less. |
| kimi-k3 | Works. Output falls 67.9%, cost falls 75.5%, and per-call input overhead drops from 99 to 32 tokens. |
| qwen3.8-max | Already off. Turning it on raises output 429% and cost 508%. |
The GLM effect is strongest on trivial prompts (38/40 at tier 1, 31/40 at tier 3), which is the opposite of what proportional deliberation would predict.
Nine configurations, three models, one platform, 18.5x spread:
| Rank | Configuration | $/request | vs cheapest |
|---|---|---|---|
| 1 | glm-5.3-flash / default | $0.00156 | 1.00x |
| 2 | glm-5.3-flash / on | $0.00157 | 1.01x |
| 3 | glm-5.3-flash / off | $0.00174 | 1.11x |
| 4 | qwen3.8-max / off | $0.00359 | 2.29x |
| 5 | qwen3.8-max / default | $0.00361 | 2.31x |
| 6 | kimi-k3 / off | $0.00651 | 4.17x |
| 7 | qwen3.8-max / on | $0.02196 | 14.04x |
| 8 | kimi-k3 / default | $0.02661 | 17.01x |
| 9 | kimi-k3 / on | $0.02892 | 18.49x |
Kimi K3 configured well (4.17x) is cheaper than Qwen3.8-Max configured badly (14.04x). One parameter moves Kimi further than switching models does.
On 20 tasks with deterministic answers and a forced output format, 899 graded responses:
| Model | Mode | pass@1 | $/correct answer | vs cheapest |
|---|---|---|---|---|
| glm-5.3-flash | off | 100.0% | $0.00018 | 1.00x |
| glm-5.3-flash | default | 100.0% | $0.00018 | 1.01x |
| glm-5.3-flash | on | 100.0% | $0.00019 | 1.05x |
| qwen3.8-max | off | 100.0% | $0.00226 | 12.38x |
| qwen3.8-max | default | 100.0% | $0.00235 | 12.85x |
| kimi-k3 | off | 98.0% | $0.00282 | 15.45x |
| qwen3.8-max | on | 100.0% | $0.00383 | 20.98x |
| kimi-k3 | default | 100.0% | $0.00565 | 30.89x |
| kimi-k3 | on | 100.0% | $0.00601 | 32.90x |
897 of 899 responses correct. Accuracy did not differentiate the models at this task difficulty, so price is the only remaining variable. The cheap model is not cheap because it is worse — at this task class it is not worse at all.
Open-ended prompts versus structured tasks with a forced answer format:
| Model | Median out (open) | Median out (structured) | Reduction |
|---|---|---|---|
| glm-5.3-flash | 1,409 | 276 | 80.4% |
| kimi-k3 | 1,133 | 248 | 78.1% |
| qwen3.8-max | 435 | 144 | 66.9% |
GLM-5.3-Flash's cost advantage over Qwen3.8-Max goes from 2.3x on open-ended prompts to 12.8x under structured output; over Kimi K3, from 17.0x to 30.7x. Verbosity is what erodes the paper advantage, and output constraints suppress verbosity more on Flash than on anything else.
Adding "Answer in one sentence" cut output 70–91% across all three models — but thinking share was unchanged (GLM 0.72 → 0.77, Kimi 0.65 → 0.65). The instruction compresses the answer, not the deliberation.
prompts.jsonl 24 open-ended prompts across 3 difficulty tiers,
plus 8 brevity-control variants. Frozen before the first call.
tasks.jsonl 20 tasks with deterministic answers and a forced answer format.
pricing.json DigitalOcean rates used for every cost figure, with snapshot date.
run.py Measurement harness. Collects, splits reasoning from answer,
reconciles against billed tokens, resumable.
score.py Grades tasks.jsonl runs, reports cost per correct answer.
analyze.py Regenerates every published number and chart.
requirements.txt Pinned dependencies.
results/ Raw JSONL logs, one record per API call.
analysis/ numbers.md and four charts, generated by analyze.py.
python3.11 -m venv .venv && source .venv/bin/activate
python -m pip install -r requirements.txt
export DO_MODEL_ACCESS_KEY=...
# smoke test first: 12 calls, a few cents
python run.py --limit 4 --reps 1 --out results/pilot.jsonl
# open-ended prompts across all three thinking modes
python run.py --reps 5 --max-tokens 32000 --out results/core-default.jsonl
python run.py --reps 5 --max-tokens 32000 --thinking on --out results/core-on.jsonl
python run.py --reps 5 --max-tokens 32000 --thinking off --out results/core-off.jsonl
# brevity control
python run.py --reps 5 --max-tokens 32000 --variant brevity-control \
--out results/brevity.jsonl
# verifiable tasks
for mode in default on off; do
python run.py --prompts tasks.jsonl --variant verifiable --reps 5 \
--max-tokens 32000 --thinking $mode --out results/verify-$mode.jsonl
done
python score.py tasks.jsonl results/verify-*.jsonl
python analyze.py --results-dir results --tasks tasks.jsonl --out-dir analysis
run.py is append-only and resumable — it keys on prompt_id::model::rep, so an
interrupted run costs nothing to restart.
Platform. DigitalOcean Serverless Inference, OpenAI-compatible endpoint at
https://inference.do-ai.run/v1. Model IDs glm-5.3-flash, qwen3.8-max,
kimi-k3. All prices are DigitalOcean's, captured on one date and recorded in
pricing.json.
No sampling parameters. Temperature, top_p and penalties are never sent. Kimi K3 uses fixed sampling values, so setting them on the other two would introduce an asymmetry. All models run at platform defaults.
Non-streaming, max_tokens=32000. An earlier run at 8,000 right-censored 20%
of GLM's tier-3 responses; the reported run has zero truncated records and every
finish_reason is stop.
Randomised execution order. The full model x prompt x repetition matrix is shuffled with a fixed seed, so platform drift spreads evenly rather than landing on whichever model ran last.
Token accounting. DigitalOcean's usage object does not break out reasoning
tokens (completion_tokens_details is null), but models expose deliberation in
a reasoning_content field on the message. We tokenize that locally with each
model's own tokenizer and reconcile against billed completion_tokens. The
residual is a constant per-model chat-template offset — GLM +2, Qwen +1, Kimi +13
— which confirms the tokenizers are correct. Shares are reported against billed
tokens, with the offset left in.
Medians, not means. Output length has a long right tail (GLM's mean is 3,111 against a median of 1,409; coefficient of variation 1.01). Means overstate typical cost. Five repetitions support a median and a range, not a tight confidence interval.
Unlabelled chain-of-thought is detected by a keyword heuristic on the visible
answer. It is a floor, not a census: it caught 103 of 120 GLM thinking-off
responses, and manual inspection suggests the true rate is higher. All
quantitative claims use billed completion_tokens, which is unambiguous.
v20, all 45 responses answered 43 and
our key said 42. The models were right; the key failed to account for the first
token arriving at TTFT. Corrected, and disclosed here.completion_tokens exceeded returned reasoning plus answer tokens by
85–391 tokens. We could not account for the difference. GLM and Qwen show no
such tail.pricing.json; re-run before relying on these
figures.Each line of a results file is one API call. Fields of interest:
| Field | Meaning |
|---|---|
completion_tokens | Billed output tokens. Authoritative. |
reasoning_tokens_local | Reasoning tokens, counted locally with the model's tokenizer |
answer_tokens_local | Visible answer tokens, same method |
reconciliation_gap | completion_tokens - (reasoning + answer). Constant per model. |
thinking_share | reasoning_tokens_local / completion_tokens. Null when reasoning was not separable — never zero. |
split_source | reasoning_content, think_tags, or none |
content_cot_suspected | Unlabelled deliberation detected in the visible answer |
thinking_mode_requested | default, on, or off |
cost_usd | Computed from pricing.json. Cached tokens are a subset of prompt_tokens, not an addition. |
truncated | finish_reason == "length". Exclude from length analysis. |
reasoning_text / answer_text | Full text, retained so the split is auditable |
Corrections welcome — open an issue. If you re-run this and get different numbers, we would like to know.
7 commits
Python
100.0%