batchwatch

batchwatch › Compare

Which half-price tier is actually fastest right now?

Every major provider now sells the same model at half price on more than one tier, so the buying question is no longer batch-or-not - it is which tier, and which model on it, lands your job in time. This page measures it. The table ranks the async batch tier - the provider's submit-and-wait API at 50% of the synchronous price - by observed median and p90, each with the sample size and the confidence it earns. Below it, the same-price flex tier - a synchronous call at the identical discount - is put head-to-head with batch at matched prompt sizes, so the choice between the two half-price tiers is made on measurement. The wait that comes with the discount is the number none of them publish, and the one we measure.

Ordered by median - and the median is not the ranking a deadline cares about. A model can sit near the top of this table and still carry the worst p90 on it. Both figures are measured and both are here: read down the p90 column when the job has a deadline.

Right now the fastest is gpt-5.6-sol at OpenAI, with a measured median of 29s — against 2 min for the slowest we can stand behind. That gap is the number nobody else publishes.

Same price, two tiers, no published latency for either

50% of synchronous OpenAI, Anthropic & Google's own published batch rate, on every input and output token

The saving is not ours to claim or inflate - it is the providers' own published price, the same at all three: a job that costs $100 synchronously costs $50 on the cheap tiers. What you trade for it is a wait, and that is the number every comparison guesses at and none of them measure. The table below is our measurement of it, one row per model - and it is yours to read for free.

The head-to-head

# Model Median (p50) p90 n Contributors Confidence
1 gpt-5.6-sol OpenAI 29s 14 min 1886 0 Low
2 gpt-5-nano OpenAI 74s 26 min 3889 0 Low
3 gpt-5.6-luna OpenAI 82s 11 min 3387 0 Low
4 claude-haiku-4-5 Anthropic 2 min 5 min 2610 0 Low
5 gemini-3.7-flash Google 2 min 3 min 2417 0 Low

Ranked by measured median, fastest first. Each model links to its full page with the distribution behind the number. Models still building a baseline are listed after the ranked ones, with the honest count.

Same price, flex vs batch

Flex and batch cost the same: OpenAI prices flex "at Batch API rates", and Google's flex is "half the Standard API" — which is exactly what its batch tier costs. When the price is identical the only questions left are the two we measure: how fast, and how often does flex refuse to run. One row per flex-capable model below, the flex tier beside the batch tier at the same price, over the last 30d (delayed 15 minutes).

Read the two latency columns differently as your prompt grows — that difference is the most useful thing on this page. A flex call is synchronous: a flex figure is the model's own work, prefill and decode, so it grows with the prompt. A batch figure is dominated by queue time — the wait to be scheduled — which is why the batch column is orders of magnitude larger at the very same prompt size. A longer prompt adds the same extra work to both, and that is the whole of the flex figure but a small fraction of the batch one. Both tiers are probed with the same fixed 8-input-token prompt and our size ladder is held out of both headlines, so neither is flattered by a different job. Take the batch column as the wait you can plan a real job against, and the flex column as the floor a larger prompt starts from — a 4,000-token flex call carries far more work than our probe does. No provider publishes a flex latency distribution at any prompt size, and we are measuring it at 3: 8, 2,000 and 16,000 input tokens, in the size ladder below. Each rung states its own count as it fills, so you can see exactly what stands behind the figure at the size you actually send.

Model Flex latency at 8 input tokens — by size Batch latency (same price, same probe size) Flex refusal rate
gemini-3.6-flash Google 1s p90 2s no batch data 3.4% refused of 5940
gpt-5.6-sol OpenAI 1s p90 2s 29s p90 14 min 14.4% refused of 5907
gpt-5-nano OpenAI 2s p90 3s 74s p90 26 min 0.1% refused of 5843
gemini-3.7-flash Google measuring (n=0) 2 min p90 3 min measuring (n=0)
Anthropic all Claude models No flex tier No flex tier — batch is the only half-price path on Claude

Flex latency is measured on a fixed 8-input-token probe, the same fixed prompt size our batch probes use. Because a flex call is synchronous, that column is a floor: it grows with the prompt, while a batch figure is dominated by the wait to be scheduled and moves far less. The refusal column is exact at this size — admission control happens before inference, so this probe measures a refusal exactly as well as a 16,000-token one would. Both latency figures come from the same measurement pipeline every other page reads; a median is shown only above 8 measurements, otherwise the honest count. Anthropic has no flex tier at all — on Claude, batch is the only half-price path in existence, which makes batch queue time more decision-critical there, not less.

Flex latency by prompt size

A longer prompt is more work for both tiers — and it is the whole of the flex figure while it is a small fraction of the batch one. A flex call is synchronous, so what you are timing IS the model's own work. A batch figure is dominated by the wait to be scheduled, so the same extra work moves it far less. That is why one probe size describes a batch queue well and describes a flex call only at that size — and it is the reason to measure the curve rather than assume it. So we run flex at 3 sizes: 8, 2,000 and 16,000 input tokens, the same rungs our batch prober sends, so the two tiers can be compared at identical prompt sizes. Over the last 30d, delayed 15 minutes; every cell carries its own n.

The number to watch is how fast the columns grow, not how far apart they start. Flex's advantage at a small prompt is enormous and published above; whether it survives a 16,000-token one is the question this table answers, and nobody else is answering it. The 8-token column is the figure the table above publishes, shown here so you can see exactly what it is the floor of; the larger rungs are held out of that headline on purpose, so a published median is never a blend of prompt sizes. The refusal rate is measured at 8 tokens, where admission control makes its decision before it reads your prompt — so it is quoted on one size, on its own, and never blended with these. A rung we have not measured is reported as unmeasured, never estimated — and 128,000 tokens, the top of our batch ladder, is one of those today.

Model 8 input tokens 2,000 input tokens 16,000 input tokens
gemini-3.6-flash Google 1s p90 2s · n=3512 measuring measuring
gpt-5-nano OpenAI 2s p90 3s · n=3994 measuring measuring
gpt-5.6-sol OpenAI 1s p90 2s · n=3122 measuring measuring

Each cell is a median with its p90 and its n, over the last 30d. A median is published above 8 measurements; below it the cell states its count instead. Sizes are the provider's OWN reported input-token count, reconciled against the size we set out to send — a probe whose prompt did not bind is excluded from every figure rather than binned into the wrong rung.

Flex availability by hour of day

The flex tier's real risk is not latency — it is refusal. A flex request that is refused does not wait in a queue; it does not run at all (OpenAI returns a 429 resource_unavailable, Google a 503 at capacity). Nobody publishes how often that happens, and the providers do not charge for the refusal — so this is the one flex number that is both decision-critical and free to measure. Below is the refusal rate we observed, by UTC hour of day, over the last 30d. Public figures are delayed 15 minutes; each hour states its own n.

This number is exact at our probe size, and that is a property of the metric rather than a claim about our sample. A refusal is decided in admission control — before inference, before the model runs at all — so our 8-token probe measures it exactly as well as a 16,000-token one would. The prompt size that governs a synchronous latency does not enter here. It is also why we can keep the probe small rather than growing it for a latency ladder: refusals cost nothing to collect, so we can run enough of them to answer by the hour.

Hour (UTC) Refusal rate Refused Served Answers (n)
00:00–00:59 UTC 1.9% refused 14 740 754 5 error
01:00–01:59 UTC 2.3% refused 17 720 737 1 error
02:00–02:59 UTC 3.7% refused 27 699 726 3 error
03:00–03:59 UTC 2.6% refused 19 708 727 7 error
04:00–04:59 UTC 2.9% refused 21 706 727 5 error
05:00–05:59 UTC 4.5% refused 33 703 736 4 error
06:00–06:59 UTC 5.7% refused 42 701 743 5 error
07:00–07:59 UTC 9.0% refused 67 676 743 2 error
08:00–08:59 UTC 10.7% refused 79 662 741 1 error
09:00–09:59 UTC 8.6% refused 64 679 743 4 error
10:00–10:59 UTC 6.6% refused 49 690 739 5 error
11:00–11:59 UTC 6.4% refused 47 690 737 4 error
12:00–12:59 UTC 7.3% refused 54 684 738 2 error
13:00–13:59 UTC 9.8% refused 71 656 727 5 error
14:00–14:59 UTC 12.4% refused 91 641 732 5 error
15:00–15:59 UTC 10.4% refused 74 640 714 5 error
16:00–16:59 UTC 7.9% refused 57 667 724 6 error
17:00–17:59 UTC 6.0% refused 44 690 734 4 error
18:00–18:59 UTC 7.4% refused 55 687 742 3 error
19:00–19:59 UTC 4.6% refused 34 700 734 3 error
20:00–20:59 UTC 5.0% refused 37 696 733 2 error
21:00–21:59 UTC 3.3% refused 25 726 751 5 error
22:00–22:59 UTC 2.0% refused 15 737 752 4 error
23:00–23:59 UTC 2.8% refused 21 735 756 3 error

Across the whole day, 6.0% of 17690 definitive flex requests were refused. An hour with fewer than 20 definitive answers (served or refused) shows "measuring" rather than a rate — a percentage on a handful is a rumour, not a measurement. Timeouts and errors are counted separately: they are "we could not tell", not "the tier said no".

This IS a time-of-day shape, and it is a measurement. The refusals cluster by hour more than a random re-labelling of the same 17690 outcomes does (permutation test over 200 shuffles, p = 0.005) — so the flex tier really is busier at some hours than others, and the refusal is a free busy-signal you can plan around. It is a second, independent confirmation that when you send matters, measured on a different mechanism from the batch queue.

Questions this answers

Which batch API is the fastest?
Right now gpt-5.6-sol at OpenAI has the fastest measured median (29s), against 2 min for the slowest model we can quote. We measure the real queue time, so this is an observation, not a guess.
How much does the batch API cost against synchronous?
50% of the synchronous rate - half price - on both input and output tokens. That is OpenAI, Anthropic and Google's own published batch price, not a batchwatch estimate. batchwatch measures the one thing they do not publish: how long the queue actually takes.
Why do some models show a count instead of a median?
Because a median on a handful of jobs is just the slowest of a handful. We publish a percentile only once a model has at least 8 measurements, so every number in the ranking is one we would stand behind. Until then the row shows the honest count rather than a figure we invented.

See it live

Every number here is measured, and it is all public.

The live dashboard shows every model with its full distribution, n and confidence grade. /v1/coverage is the same data as JSON, no key required. Send five measurements in seven days and the delay is gone: you read every figure live, and the decision endpoints open (/v1/should-i-batch, /v1/estimate-batchtime).